aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/pdfbox/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/pdfbox/util')
-rw-r--r--src/main/java/org/pdfbox/util/BitFlagHelper.java85
-rw-r--r--src/main/java/org/pdfbox/util/BoundingBox.java188
-rw-r--r--src/main/java/org/pdfbox/util/DateConverter.java281
-rw-r--r--src/main/java/org/pdfbox/util/DefaultFileFilter.java285
-rw-r--r--src/main/java/org/pdfbox/util/ErrorLogger.java72
-rw-r--r--src/main/java/org/pdfbox/util/ImageParameters.java234
-rw-r--r--src/main/java/org/pdfbox/util/Matrix.java350
-rw-r--r--src/main/java/org/pdfbox/util/PDFHighlighter.java213
-rw-r--r--src/main/java/org/pdfbox/util/PDFOperator.java153
-rw-r--r--src/main/java/org/pdfbox/util/PDFStreamEngine.java622
-rw-r--r--src/main/java/org/pdfbox/util/PDFText2HTML.java271
-rw-r--r--src/main/java/org/pdfbox/util/PDFTextStripper.java1033
-rw-r--r--src/main/java/org/pdfbox/util/PDFTextStripperByArea.java165
-rw-r--r--src/main/java/org/pdfbox/util/ResourceLoader.java169
-rw-r--r--src/main/java/org/pdfbox/util/SimpleConfigurator.java68
-rw-r--r--src/main/java/org/pdfbox/util/Splitter.java201
-rw-r--r--src/main/java/org/pdfbox/util/TextPosition.java203
-rw-r--r--src/main/java/org/pdfbox/util/TextPositionComparator.java126
-rw-r--r--src/main/java/org/pdfbox/util/XMLUtil.java103
-rw-r--r--src/main/java/org/pdfbox/util/operator/BeginText.java68
-rw-r--r--src/main/java/org/pdfbox/util/operator/Concatenate.java106
-rw-r--r--src/main/java/org/pdfbox/util/operator/EndText.java67
-rw-r--r--src/main/java/org/pdfbox/util/operator/GRestore.java67
-rw-r--r--src/main/java/org/pdfbox/util/operator/GSave.java66
-rw-r--r--src/main/java/org/pdfbox/util/operator/Invoke.java113
-rw-r--r--src/main/java/org/pdfbox/util/operator/MoveAndShow.java75
-rw-r--r--src/main/java/org/pdfbox/util/operator/MoveText.java76
-rw-r--r--src/main/java/org/pdfbox/util/operator/MoveTextSetLeading.java80
-rw-r--r--src/main/java/org/pdfbox/util/operator/NextLine.java82
-rw-r--r--src/main/java/org/pdfbox/util/operator/OperatorProcessor.java93
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetCharSpacing.java79
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetGraphicsStateParameters.java72
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetHorizontalTextScaling.java64
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetLineWidth.java64
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetMatrix.java90
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetMoveAndShow.java80
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetNonStrokingCMYKColor.java69
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetNonStrokingColorSpace.java86
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetNonStrokingRGBColor.java69
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetStrokingCMYKColor.java71
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetStrokingColorSpace.java89
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetStrokingRGBColor.java71
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetTextFont.java96
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetTextLeading.java69
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetTextRenderingMode.java64
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetTextRise.java64
-rw-r--r--src/main/java/org/pdfbox/util/operator/SetWordSpacing.java68
-rw-r--r--src/main/java/org/pdfbox/util/operator/ShowText.java73
-rw-r--r--src/main/java/org/pdfbox/util/operator/ShowTextGlyph.java99
-rw-r--r--src/main/java/org/pdfbox/util/operator/package.html9
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/AppendRectangleToPath.java77
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/BeginInlineImage.java114
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/ClosePath.java59
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/CurveTo.java73
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateFinalPoint.java69
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateInitialPoint.java76
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/FillEvenOddRule.java71
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/FillNonZeroRule.java71
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/Invoke.java180
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/LineTo.java65
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/MoveTo.java68
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/SetLineWidth.java65
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingCMYKColor.java64
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingColorSpace.java71
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingRGBColor.java65
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingCMYKColor.java64
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingColorSpace.java70
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingRGBColor.java65
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/StrokePath.java73
-rw-r--r--src/main/java/org/pdfbox/util/operator/pagedrawer/package.html9
-rw-r--r--src/main/java/org/pdfbox/util/package.html9
71 files changed, 8639 insertions, 0 deletions
diff --git a/src/main/java/org/pdfbox/util/BitFlagHelper.java b/src/main/java/org/pdfbox/util/BitFlagHelper.java
new file mode 100644
index 0000000..058f733
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/BitFlagHelper.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 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.util;
+
+import org.pdfbox.cos.COSDictionary;
+
+/**
+ * This class will be used for bit flag operations.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.2 $
+ */
+public class BitFlagHelper
+{
+ private BitFlagHelper()
+ {
+ //helper class should not be constructed
+ }
+
+ /**
+ * Sets the given boolean value at bitPos in the flags.
+ *
+ * @param dic The dictionary to set the value into.
+ * @param field The name of the field to set the value into.
+ * @param bitFlag the bit position to set the value in.
+ * @param value the value the bit position should have.
+ */
+ public static void setFlag( COSDictionary dic, String field, int bitFlag, boolean value )
+ {
+ int currentFlags = dic.getInt( field, 0 );
+ if( value )
+ {
+ currentFlags = currentFlags | bitFlag;
+ }
+ else
+ {
+ currentFlags = currentFlags &= ~bitFlag;
+ }
+ dic.setInt( field, currentFlags );
+ }
+
+ /**
+ * Gets the boolean value from the flags at the given bit
+ * position.
+ *
+ * @param dic The dictionary to get the field from.
+ * @param field The name of the field to get the flag from.
+ * @param bitFlag the bitPosition to get the value from.
+ *
+ * @return true if the number at bitPos is '1'
+ */
+ public static boolean getFlag(COSDictionary dic, String field, int bitFlag)
+ {
+ int ff = dic.getInt( field, 0 );
+ return (ff & bitFlag) == bitFlag;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/BoundingBox.java b/src/main/java/org/pdfbox/util/BoundingBox.java
new file mode 100644
index 0000000..aaea354
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/BoundingBox.java
@@ -0,0 +1,188 @@
+/**
+ * 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.util;
+
+import java.awt.Point;
+
+/**
+ * This is an implementation of a bounding box. This was originally written for the
+ * AMF parser.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.6 $
+ */
+public class BoundingBox
+{
+ private float lowerLeftX;
+ private float lowerLeftY;
+ private float upperRightX;
+ private float upperRightY;
+
+ /**
+ * Getter for property lowerLeftX.
+ *
+ * @return Value of property lowerLeftX.
+ */
+ public float getLowerLeftX()
+ {
+ return lowerLeftX;
+ }
+
+ /**
+ * Setter for property lowerLeftX.
+ *
+ * @param lowerLeftXValue New value of property lowerLeftX.
+ */
+ public void setLowerLeftX(float lowerLeftXValue)
+ {
+ this.lowerLeftX = lowerLeftXValue;
+ }
+
+ /**
+ * Getter for property lowerLeftY.
+ *
+ * @return Value of property lowerLeftY.
+ */
+ public float getLowerLeftY()
+ {
+ return lowerLeftY;
+ }
+
+ /**
+ * Setter for property lowerLeftY.
+ *
+ * @param lowerLeftYValue New value of property lowerLeftY.
+ */
+ public void setLowerLeftY(float lowerLeftYValue)
+ {
+ this.lowerLeftY = lowerLeftYValue;
+ }
+
+ /**
+ * Getter for property upperRightX.
+ *
+ * @return Value of property upperRightX.
+ */
+ public float getUpperRightX()
+ {
+ return upperRightX;
+ }
+
+ /**
+ * Setter for property upperRightX.
+ *
+ * @param upperRightXValue New value of property upperRightX.
+ */
+ public void setUpperRightX(float upperRightXValue)
+ {
+ this.upperRightX = upperRightXValue;
+ }
+
+ /**
+ * Getter for property upperRightY.
+ *
+ * @return Value of property upperRightY.
+ */
+ public float getUpperRightY()
+ {
+ return upperRightY;
+ }
+
+ /**
+ * Setter for property upperRightY.
+ *
+ * @param upperRightYValue New value of property upperRightY.
+ */
+ public void setUpperRightY(float upperRightYValue)
+ {
+ this.upperRightY = upperRightYValue;
+ }
+
+ /**
+ * This will get the width of this rectangle as calculated by
+ * upperRightX - lowerLeftX.
+ *
+ * @return The width of this rectangle.
+ */
+ public float getWidth()
+ {
+ return getUpperRightX() - getLowerLeftX();
+ }
+
+ /**
+ * This will get the height of this rectangle as calculated by
+ * upperRightY - lowerLeftY.
+ *
+ * @return The height of this rectangle.
+ */
+ public float getHeight()
+ {
+ return getUpperRightY() - getLowerLeftY();
+ }
+
+ /**
+ * Checks if a point is inside this rectangle.
+ *
+ * @param x The x coordinate.
+ * @param y The y coordinate.
+ *
+ * @return true If the point is on the edge or inside the rectangle bounds.
+ */
+ public boolean contains( float x, float y )
+ {
+ return x >= lowerLeftX && x <= upperRightX &&
+ y >= lowerLeftY && y <= upperRightY;
+ }
+
+ /**
+ * Checks if a point is inside this rectangle.
+ *
+ * @param point The point to check
+ *
+ * @return true If the point is on the edge or inside the rectangle bounds.
+ */
+ public boolean contains( Point point )
+ {
+ return contains( (float)point.getX(), (float)point.getY() );
+ }
+
+ /**
+ * This will return a string representation of this rectangle.
+ *
+ * @return This object as a string.
+ */
+ public String toString()
+ {
+ return "[" + getLowerLeftX() + "," + getLowerLeftY() + "," +
+ getUpperRightX() + "," + getUpperRightY() +"]";
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/DateConverter.java b/src/main/java/org/pdfbox/util/DateConverter.java
new file mode 100644
index 0000000..43d3566
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/DateConverter.java
@@ -0,0 +1,281 @@
+/**
+ * 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.util;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+import java.io.IOException;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+
+import org.pdfbox.cos.COSString;
+
+/**
+ * This class is used to convert dates to strings and back using the PDF
+ * date standards. Date are described in PDFReference1.4 section 3.8.2
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.9 $
+ */
+public class DateConverter
+{
+ private static final SimpleDateFormat PDF_DATE_FORMAT = new SimpleDateFormat( "yyyyMMddHHmmss" );
+
+ //The Date format is supposed to be the PDF_DATE_FORMAT, but not all PDF documents
+ //will use that date, so I have added a couple other potential formats
+ //to try if the original one does not work.
+ private static final SimpleDateFormat[] POTENTIAL_FORMATS = new SimpleDateFormat[] {
+ new SimpleDateFormat("EEEE, dd MMM yyyy hh:mm:ss a"),
+ new SimpleDateFormat("EEEE, MMM dd, yyyy hh:mm:ss a")};
+
+ private static final SimpleDateFormat ISO_8601_DATE_FORMAT = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss" );
+
+ private DateConverter()
+ {
+ //utility class should not be constructed.
+ }
+
+ /**
+ * This will convert the calendar to a string.
+ *
+ * @param date The date to convert to a string.
+ *
+ * @return The date as a String to be used in a PDF document.
+ */
+ public static String toString( Calendar date )
+ {
+ String retval = null;
+ if( date != null )
+ {
+ StringBuffer buffer = new StringBuffer();
+ TimeZone zone = date.getTimeZone();
+ long offsetInMinutes = zone.getOffset( date.getTimeInMillis() )/1000/60;
+ long hours = Math.abs( offsetInMinutes/60 );
+ long minutes = Math.abs( offsetInMinutes%60 );
+ buffer.append( "D:" );
+ buffer.append( PDF_DATE_FORMAT.format( date.getTime() ) );
+ if( offsetInMinutes == 0 )
+ {
+ buffer.append( "Z" );
+ }
+ else if( offsetInMinutes < 0 )
+ {
+ buffer.append( "-" );
+ }
+ else
+ {
+ buffer.append( "+" );
+ }
+ if( hours < 10 )
+ {
+ buffer.append( "0" );
+ }
+ buffer.append( hours );
+ buffer.append( "'" );
+ if( minutes < 10 )
+ {
+ buffer.append( "0" );
+ }
+ buffer.append( minutes );
+ buffer.append( "'" );
+ retval = buffer.toString();
+
+ }
+ return retval;
+ }
+
+ /**
+ * This will convert a string to a calendar.
+ *
+ * @param date The string representation of the calendar.
+ *
+ * @return The calendar that this string represents.
+ *
+ * @throws IOException If the date string is not in the correct format.
+ */
+ public static Calendar toCalendar( COSString date ) throws IOException
+ {
+ Calendar retval = null;
+ if( date != null )
+ {
+ retval = toCalendar( date.getString() );
+ }
+
+ return retval;
+ }
+
+ /**
+ * This will convert a string to a calendar.
+ *
+ * @param date The string representation of the calendar.
+ *
+ * @return The calendar that this string represents.
+ *
+ * @throws IOException If the date string is not in the correct format.
+ */
+ public static Calendar toCalendar( String date ) throws IOException
+ {
+ Calendar retval = null;
+ if( date != null )
+ {
+ //these are the default values
+ int year = 0;
+ int month = 1;
+ int day = 1;
+ int hour = 0;
+ int minute = 0;
+ int second = 0;
+ //first string off the prefix if it exists
+ try
+ {
+ SimpleTimeZone zone = null;
+ if( date.startsWith( "D:" ) )
+ {
+ date = date.substring( 2, date.length() );
+ }
+ if( date.length() < 4 )
+ {
+ throw new IOException( "Error: Invalid date format '" + date + "'" );
+ }
+ year = Integer.parseInt( date.substring( 0, 4 ) );
+ if( date.length() >= 6 )
+ {
+ month = Integer.parseInt( date.substring( 4, 6 ) );
+ }
+ if( date.length() >= 8 )
+ {
+ day = Integer.parseInt( date.substring( 6, 8 ) );
+ }
+ if( date.length() >= 10 )
+ {
+ hour = Integer.parseInt( date.substring( 8, 10 ) );
+ }
+ if( date.length() >= 12 )
+ {
+ minute = Integer.parseInt( date.substring( 10, 12 ) );
+ }
+ if( date.length() >= 14 )
+ {
+ second = Integer.parseInt( date.substring( 12, 14 ) );
+ }
+ retval = new GregorianCalendar( year, month-1, day, hour, minute, second );
+ if( date.length() >= 15 )
+ {
+ char sign = date.charAt( 14 );
+ if( sign == 'Z' )
+ {
+ zone = new SimpleTimeZone(0,"Unknown");
+ }
+ else
+ {
+ int hours = 0;
+ int minutes = 0;
+ if( date.length() >= 17 )
+ {
+ hours = Integer.parseInt( date.substring( 15, 17 ) );
+ }
+ if( date.length() > 20 )
+ {
+ minutes = Integer.parseInt( date.substring( 18, 20 ) );
+ }
+ zone = new SimpleTimeZone( hours*60*60*1000 + minutes*60*1000, "Unknown" );
+ }
+ retval.setTimeZone( zone );
+ }
+ }
+ catch( NumberFormatException e )
+ {
+ for( int i=0; retval == null && i<POTENTIAL_FORMATS.length; i++ )
+ {
+ try
+ {
+ Date utilDate = POTENTIAL_FORMATS[i].parse( date );
+ retval = new GregorianCalendar();
+ retval.setTime( utilDate );
+ }
+ catch( ParseException pe )
+ {
+ //ignore and move to next potential format
+ }
+ }
+ if( retval == null )
+ {
+ //we didn't find a valid date format so throw an exception
+ throw new IOException( "Error converting date:" + date );
+ }
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * Convert the date to iso 8601 string format.
+ *
+ * @param cal The date to convert.
+ * @return The date represented as an ISO 8601 string.
+ */
+ public static String toISO8601( Calendar cal )
+ {
+ StringBuffer retval = new StringBuffer();
+ retval.append( ISO_8601_DATE_FORMAT.format( cal.getTime() ) );
+ int timeZone = cal.get( Calendar.ZONE_OFFSET );
+ if( timeZone < 0 )
+ {
+ retval.append( "-" );
+ }
+ else
+ {
+ retval.append( "+" );
+ }
+ timeZone = Math.abs( timeZone );
+ //milliseconds/1000 = seconds = seconds / 60 = minutes = minutes/60 = hours
+ int hours = timeZone/1000/60/60;
+ int minutes = (timeZone - (hours*1000*60*60))/1000/1000;
+ if( hours < 10 )
+ {
+ retval.append( "0" );
+ }
+ retval.append( Integer.toString( hours ) );
+ retval.append( ":" );
+ if( minutes < 10 )
+ {
+ retval.append( "0" );
+ }
+ retval.append( Integer.toString( minutes ) );
+
+ return retval.toString();
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/DefaultFileFilter.java b/src/main/java/org/pdfbox/util/DefaultFileFilter.java
new file mode 100644
index 0000000..e4baec0
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/DefaultFileFilter.java
@@ -0,0 +1,285 @@
+/*
+ * @(#)DefaultFileFilter.java 1.12 01/12/03
+ *
+ * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+package org.pdfbox.util;
+
+import java.io.File;
+import java.util.Hashtable;
+import java.util.Enumeration;
+//import javax.swing.*;
+import javax.swing.filechooser.FileFilter;
+
+/**
+ * A convenience implementation of FileFilter that filters out
+ * all files except for those type extensions that it knows about.
+ *
+ * Extensions are of the type ".foo", which is typically found on
+ * Windows and Unix boxes, but not on Macinthosh. Case is ignored.
+ *
+ * Example - create a new filter that filerts out all files
+ * but gif and jpg image files:
+ *
+ * JFileChooser chooser = new JFileChooser();
+ * DefaultFileFilter filter = new DefaultFileFilter(
+ * new String{"gif", "jpg"}, "JPEG & GIF Images")
+ * chooser.addChoosableFileFilter(filter);
+ * chooser.showOpenDialog(this);
+ *
+ * @version $Revision: 1.2 $
+ * @author Jeff Dinkins
+ */
+public class DefaultFileFilter extends FileFilter
+{
+
+ private static final String TYPE_UNKNOWN = "Type Unknown";
+ private static final String HIDDEN_FILE = "Hidden File";
+
+ private Hashtable filters = null;
+ private String description = null;
+ private String fullDescription = null;
+ private boolean useExtensionsInDescription = true;
+
+ /**
+ * Creates a file filter. If no filters are added, then all
+ * files are accepted.
+ *
+ * @see #addExtension
+ */
+ public DefaultFileFilter()
+ {
+ this.filters = new Hashtable();
+ }
+
+ /**
+ * Creates a file filter that accepts files with the given extension.
+ * Example: new DefaultFileFilter("jpg");
+ *
+ * @see #addExtension
+ */
+ public DefaultFileFilter(String extension)
+ {
+ this(extension,null);
+ }
+
+ /**
+ * Creates a file filter that accepts the given file type.
+ * Example: new DefaultFileFilter("jpg", "JPEG Image Images");
+ *
+ * Note that the "." before the extension is not needed. If
+ * provided, it will be ignored.
+ *
+ * @see #addExtension
+ */
+ public DefaultFileFilter(String extension, String desc)
+ {
+ this();
+ if(extension!=null)
+ {
+ addExtension(extension);
+ }
+ if(desc!=null)
+ {
+ setDescription(desc);
+ }
+ }
+
+ /**
+ * Creates a file filter from the given string array.
+ * Example: new DefaultFileFilter(String {"gif", "jpg"});
+ *
+ * Note that the "." before the extension is not needed adn
+ * will be ignored.
+ *
+ * @see #addExtension
+ */
+ public DefaultFileFilter(String[] filterArray)
+ {
+ this(filterArray, null);
+ }
+
+ /**
+ * Creates a file filter from the given string array and description.
+ * Example: new DefaultFileFilter(String {"gif", "jpg"}, "Gif and JPG Images");
+ *
+ * Note that the "." before the extension is not needed and will be ignored.
+ *
+ * @see #addExtension
+ */
+ public DefaultFileFilter(String[] filterArray, String desc)
+ {
+ this();
+ for (int i = 0; i < filterArray.length; i++)
+ {
+ // add filters one by one
+ addExtension(filterArray[i]);
+ }
+ if(desc!=null)
+ {
+ setDescription(desc);
+ }
+ }
+
+ /**
+ * Files that begin with "." are ignored.
+ *
+ * @param f The file to accept.
+ * @return true if this file should be shown in the directory pane, false if it shouldn't.
+ * @see #getExtension
+ * @see FileFilter#accepts
+ */
+ public boolean accept(File f)
+ {
+ if(f != null)
+ {
+ if(f.isDirectory())
+ {
+ return true;
+ }
+ String extension = getExtension(f);
+ if(extension != null && filters.get(getExtension(f)) != null)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return the extension portion of the file's name .
+ *
+ * @param f The file to get the extension of.
+ * @return The extension of a file.
+ * @see #getExtension
+ * @see FileFilter#accept
+ */
+ public String getExtension(File f)
+ {
+ if(f != null)
+ {
+ String filename = f.getName();
+ int i = filename.lastIndexOf('.');
+ if(i>0 && i<filename.length()-1)
+ {
+ return filename.substring(i+1).toLowerCase();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Adds a filetype "dot" extension to filter against.
+ *
+ * For example: the following code will create a filter that filters
+ * out all files except those that end in ".jpg" and ".tif":
+ *
+ * DefaultFileFilter filter = new DefaultFileFilter();
+ * filter.addExtension("jpg");
+ * filter.addExtension("tif");
+ *
+ * Note that the "." before the extension is not needed and will be ignored.
+ *
+ * @param extension The new extension to add.
+ */
+ public void addExtension(String extension)
+ {
+ if(filters == null)
+ {
+ filters = new Hashtable(5);
+ }
+ filters.put(extension.toLowerCase(), this);
+ fullDescription = null;
+ }
+
+
+ /**
+ * Returns the human readable description of this filter. For
+ * example: "JPEG and GIF Image Files (*.jpg, *.gif)"
+ *
+ * @see setDescription
+ * @see setExtensionListInDescription
+ * @see isExtensionListInDescription
+ * @see FileFilter#getDescription
+ *
+ * @return The human readable description of this filter.
+ */
+ public String getDescription()
+ {
+ if(fullDescription == null)
+ {
+ if(description == null || isExtensionListInDescription())
+ {
+ fullDescription = description==null ? "(" : description + " (";
+ // build the description from the extension list
+ Enumeration extensions = filters.keys();
+ if(extensions != null)
+ {
+ fullDescription += "." + (String) extensions.nextElement();
+ while (extensions.hasMoreElements())
+ {
+ fullDescription += ", ." + (String) extensions.nextElement();
+ }
+ }
+ fullDescription += ")";
+ }
+ else
+ {
+ fullDescription = description;
+ }
+ }
+ return fullDescription;
+ }
+
+ /**
+ * Sets the human readable description of this filter. For
+ * example: filter.setDescription("Gif and JPG Images");
+ *
+ * @param desc the new description for the file.
+ * @see setDescription
+ * @see setExtensionListInDescription
+ * @see isExtensionListInDescription
+ */
+ public void setDescription(String desc)
+ {
+ description = desc;
+ fullDescription = null;
+ }
+
+ /**
+ * Determines whether the extension list (.jpg, .gif, etc) should
+ * show up in the human readable description.
+ *
+ * Only relevent if a description was provided in the constructor
+ * or using setDescription();
+ *
+ *
+ * @param b Tell if the extionsion shoud show up in human readable description.
+ * @see getDescription
+ * @see setDescription
+ * @see isExtensionListInDescription
+ */
+ public void setExtensionListInDescription(boolean b)
+ {
+ useExtensionsInDescription = b;
+ fullDescription = null;
+ }
+
+ /**
+ * @return whether the extension list (.jpg, .gif, etc) should
+ * show up in the human readable description.
+ *
+ * Only relevent if a description was provided in the constructor
+ * or using setDescription();
+ *
+ *
+ * @see getDescription
+ * @see setDescription
+ * @see setExtensionListInDescription
+ */
+ public boolean isExtensionListInDescription()
+ {
+ return useExtensionsInDescription;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/ErrorLogger.java b/src/main/java/org/pdfbox/util/ErrorLogger.java
new file mode 100644
index 0000000..b2f380c
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/ErrorLogger.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 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.util;
+
+/**
+ * This class deals with some logging that is not handled by the log4j replacement.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.2 $
+ */
+public class ErrorLogger
+{
+ /**
+ * Utility class, should not be instantiated.
+ *
+ */
+ private ErrorLogger()
+ {
+ }
+
+ /**
+ * Log an error message. This is only used for log4j replacement and
+ * should never be used when writing code.
+ *
+ * @param errorMessage The error message.
+ */
+ public static void log( String errorMessage )
+ {
+ System.err.println( errorMessage );
+ }
+
+ /**
+ * Log an error message. This is only used for log4j replacement and
+ * should never be used when writing code.
+ *
+ * @param errorMessage The error message.
+ * @param t The exception.
+ */
+ public static void log( String errorMessage, Throwable t )
+ {
+ System.err.println( errorMessage );
+ t.printStackTrace();
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/ImageParameters.java b/src/main/java/org/pdfbox/util/ImageParameters.java
new file mode 100644
index 0000000..79f09b0
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/ImageParameters.java
@@ -0,0 +1,234 @@
+/**
+ * Copyright (c) 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.util;
+
+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.COSArrayList;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpaceFactory;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * This contains all of the image parameters for in inlined image.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.3 $
+ */
+public class ImageParameters
+{
+ private COSDictionary dictionary;
+
+ /**
+ * Constructor.
+ */
+ public ImageParameters()
+ {
+ dictionary = new COSDictionary();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param params The image parameters.
+ */
+ public ImageParameters( COSDictionary params )
+ {
+ dictionary = params;
+ }
+
+ /**
+ * This will get the dictionary that stores the image parameters.
+ *
+ * @return The COS dictionary that stores the image parameters.
+ */
+ public COSDictionary getDictionary()
+ {
+ return dictionary;
+ }
+
+ private COSBase getCOSObject( String abbreviatedName, String name )
+ {
+ COSBase retval = dictionary.getDictionaryObject( COSName.getPDFName( abbreviatedName ) );
+ if( retval == null )
+ {
+ retval = dictionary.getDictionaryObject( COSName.getPDFName( name ) );
+ }
+ return retval;
+ }
+
+ private int getNumberOrNegativeOne( String abbreviatedName, String name )
+ {
+ int retval = -1;
+ COSNumber number = (COSNumber)getCOSObject( abbreviatedName, name );
+ if( number != null )
+ {
+ retval = number.intValue();
+ }
+ return retval;
+ }
+
+ /**
+ * The bits per component of this image. This will return -1 if one has not
+ * been set.
+ *
+ * @return The number of bits per component.
+ */
+ public int getBitsPerComponent()
+ {
+ return getNumberOrNegativeOne( "BPC", "BitsPerComponent" );
+ }
+
+ /**
+ * Set the number of bits per component.
+ *
+ * @param bpc The number of bits per component.
+ */
+ public void setBitsPerComponent( int bpc )
+ {
+ dictionary.setItem( COSName.getPDFName( "BPC" ), new COSInteger( bpc ) );
+ }
+
+
+ /**
+ * This will get the color space or null if none exists.
+ *
+ * @return The color space for this image.
+ *
+ * @throws IOException If there is an error getting the colorspace.
+ */
+ public PDColorSpace getColorSpace() throws IOException
+ {
+ COSBase cs = getCOSObject( "CS", "ColorSpace" );
+ PDColorSpace retval = null;
+ if( cs != null )
+ {
+ retval = PDColorSpaceFactory.createColorSpace( cs );
+ }
+ return retval;
+ }
+
+ /**
+ * This will set the color space for this image.
+ *
+ * @param cs The color space for this image.
+ */
+ public void setColorSpace( PDColorSpace cs )
+ {
+ COSBase base = null;
+ if( cs != null )
+ {
+ base = cs.getCOSObject();
+ }
+ dictionary.setItem( COSName.getPDFName( "CS" ), base );
+ }
+
+ /**
+ * The height of this image. This will return -1 if one has not
+ * been set.
+ *
+ * @return The height.
+ */
+ public int getHeight()
+ {
+ return getNumberOrNegativeOne( "H", "Height" );
+ }
+
+ /**
+ * Set the height of the image.
+ *
+ * @param h The height of the image.
+ */
+ public void setHeight( int h )
+ {
+ dictionary.setItem( COSName.getPDFName( "H" ), new COSInteger( h ) );
+ }
+
+ /**
+ * The width of this image. This will return -1 if one has not
+ * been set.
+ *
+ * @return The width.
+ */
+ public int getWidth()
+ {
+ return getNumberOrNegativeOne( "W", "Width" );
+ }
+
+ /**
+ * Set the width of the image.
+ *
+ * @param w The width of the image.
+ */
+ public void setWidth( int w )
+ {
+ dictionary.setItem( COSName.getPDFName( "W" ), new COSInteger( w ) );
+ }
+
+ /**
+ * This will get the list of filters that are associated with this stream. Or
+ * null if there are none.
+ * @return A list of all encoding filters to apply to this stream.
+ */
+ public List getFilters()
+ {
+ List retval = null;
+ COSBase filters = dictionary.getDictionaryObject( new String[] {"Filter", "F"} );
+ if( filters instanceof COSName )
+ {
+ COSName name = (COSName)filters;
+ retval = new COSArrayList( name.getName(), name, dictionary, "Filter" );
+ }
+ else if( filters instanceof COSArray )
+ {
+ retval = COSArrayList.convertCOSNameCOSArrayToList( (COSArray)filters );
+ }
+ return retval;
+ }
+
+ /**
+ * This will set the filters that are part of this stream.
+ *
+ * @param filters The filters that are part of this stream.
+ */
+ public void setFilters( List filters )
+ {
+ COSBase obj = COSArrayList.convertStringListToCOSNameCOSArray( filters );
+ dictionary.setItem( "Filter", obj );
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/Matrix.java b/src/main/java/org/pdfbox/util/Matrix.java
new file mode 100644
index 0000000..ff14887
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/Matrix.java
@@ -0,0 +1,350 @@
+/**
+ * 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.util;
+
+import java.awt.geom.AffineTransform;
+
+/**
+ * This class will be used for matrix manipulation.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.13 $
+ */
+public class Matrix implements Cloneable
+{
+ private float[] single =
+ {
+ 1,0,0,
+ 0,1,0,
+ 0,0,1
+ };
+
+ /**
+ * Constructor.
+ */
+ public Matrix()
+ {
+ //default constructor
+ }
+
+ /**
+ * Create an affine transform from this matrix's values.
+ *
+ * @return An affine transform with this matrix's values.
+ */
+ public AffineTransform createAffineTransform()
+ {
+ AffineTransform retval = new AffineTransform(
+ single[0], single[1],
+ single[3], single[4],
+ single[6], single[7] );
+ return retval;
+ }
+
+ /**
+ * Set the values of the matrix from the AffineTransform.
+ *
+ * @param af The transform to get the values from.
+ */
+ public void setFromAffineTransform( AffineTransform af )
+ {
+ single[0] = (float)af.getScaleX();
+ single[1] = (float)af.getShearY();
+ single[3] = (float)af.getShearX();
+ single[4] = (float)af.getScaleY();
+ single[6] = (float)af.getTranslateX();
+ single[7] = (float)af.getTranslateY();
+ }
+
+ /**
+ * This will get a matrix value at some point.
+ *
+ * @param row The row to get the value from.
+ * @param column The column to get the value from.
+ *
+ * @return The value at the row/column position.
+ */
+ public float getValue( int row, int column )
+ {
+ return single[row*3+column];
+ }
+
+ /**
+ * This will set a value at a position.
+ *
+ * @param row The row to set the value at.
+ * @param column the column to set the value at.
+ * @param value The value to set at the position.
+ */
+ public void setValue( int row, int column, float value )
+ {
+ single[row*3+column] = value;
+ }
+
+ /**
+ * Return a single dimension array of all values in the matrix.
+ *
+ * @return The values ot this matrix.
+ */
+ public float[][] getValues()
+ {
+ float[][] retval = new float[3][3];
+ retval[0][0] = single[0];
+ retval[0][1] = single[1];
+ retval[0][2] = single[2];
+ retval[1][0] = single[3];
+ retval[1][1] = single[4];
+ retval[1][2] = single[5];
+ retval[2][0] = single[6];
+ retval[2][1] = single[7];
+ retval[2][2] = single[8];
+ return retval;
+ }
+
+ /**
+ * Return a single dimension array of all values in the matrix.
+ *
+ * @return The values ot this matrix.
+ */
+ public double[][] getValuesAsDouble()
+ {
+ double[][] retval = new double[3][3];
+ retval[0][0] = single[0];
+ retval[0][1] = single[1];
+ retval[0][2] = single[2];
+ retval[1][0] = single[3];
+ retval[1][1] = single[4];
+ retval[1][2] = single[5];
+ retval[2][0] = single[6];
+ retval[2][1] = single[7];
+ retval[2][2] = single[8];
+ return retval;
+ }
+
+ /**
+ * This will take the current matrix and multipy it with a matrix that is passed in.
+ *
+ * @param b The matrix to multiply by.
+ *
+ * @return The result of the two multiplied matrices.
+ */
+ public Matrix multiply( Matrix b )
+ {
+ Matrix result = new Matrix();
+
+ float[] bMatrix = b.single;
+ float[] resultMatrix = result.single;
+ resultMatrix[0] = single[0] * bMatrix[0] + single[1] * bMatrix[3] + single[2] * bMatrix[6];
+ resultMatrix[1] = single[0] * bMatrix[1] + single[1] * bMatrix[4] + single[2] * bMatrix[7];
+ resultMatrix[2] = single[0] * bMatrix[2] + single[1] * bMatrix[5] + single[2] * bMatrix[8];
+ resultMatrix[3] = single[3] * bMatrix[0] + single[4] * bMatrix[3] + single[5] * bMatrix[6];
+ resultMatrix[4] = single[3] * bMatrix[1] + single[4] * bMatrix[4] + single[5] * bMatrix[7];
+ resultMatrix[5] = single[3] * bMatrix[2] + single[4] * bMatrix[5] + single[5] * bMatrix[8];
+ resultMatrix[6] = single[6] * bMatrix[0] + single[7] * bMatrix[3] + single[8] * bMatrix[6];
+ resultMatrix[7] = single[6] * bMatrix[1] + single[7] * bMatrix[4] + single[8] * bMatrix[7];
+ resultMatrix[8] = single[6] * bMatrix[2] + single[7] * bMatrix[5] + single[8] * bMatrix[8];
+
+ return result;
+ }
+
+ /**
+ * Create a new matrix with just the scaling operators.
+ *
+ * @return A new matrix with just the scaling operators.
+ */
+ public Matrix extractScaling()
+ {
+ Matrix retval = new Matrix();
+
+ retval.single[0] = this.single[0];
+ retval.single[4] = this.single[4];
+
+ return retval;
+ }
+
+ /**
+ * Convenience method to create a scaled instance.
+ *
+ * @param x The xscale operator.
+ * @param y The yscale operator.
+ * @return A new matrix with just the x/y scaling
+ */
+ public static Matrix getScaleInstance( float x, float y)
+ {
+ Matrix retval = new Matrix();
+
+ retval.single[0] = x;
+ retval.single[4] = y;
+
+ return retval;
+ }
+
+ /**
+ * Create a new matrix with just the translating operators.
+ *
+ * @return A new matrix with just the translating operators.
+ */
+ public Matrix extractTranslating()
+ {
+ Matrix retval = new Matrix();
+
+ retval.single[6] = this.single[6];
+ retval.single[7] = this.single[7];
+
+ return retval;
+ }
+
+ /**
+ * Convenience method to create a translating instance.
+ *
+ * @param x The x translating operator.
+ * @param y The y translating operator.
+ * @return A new matrix with just the x/y translating.
+ */
+ public static Matrix getTranslatingInstance( float x, float y)
+ {
+ Matrix retval = new Matrix();
+
+ retval.single[6] = x;
+ retval.single[7] = y;
+
+ return retval;
+ }
+
+ /**
+ * Clones this object.
+ * @return cloned matrix as an object.
+ */
+ public Object clone()
+ {
+ Matrix clone = new Matrix();
+ System.arraycopy( single, 0, clone.single, 0, 9 );
+ return clone;
+ }
+
+ /**
+ * This will copy the text matrix data.
+ *
+ * @return a matrix that matches this one.
+ */
+ public Matrix copy()
+ {
+ return (Matrix) clone();
+ }
+
+ /**
+ * This will return a string representation of the matrix.
+ *
+ * @return The matrix as a string.
+ */
+ public String toString()
+ {
+ StringBuffer result = new StringBuffer( "" );
+ result.append( "[[" );
+ result.append( single[0] + "," );
+ result.append( single[1] + "," );
+ result.append( single[2] + "][");
+ result.append( single[3] + "," );
+ result.append( single[4] + "," );
+ result.append( single[5] + "][");
+ result.append( single[6] + "," );
+ result.append( single[7] + "," );
+ result.append( single[8] + "]]");
+
+ return result.toString();
+ }
+
+ /**
+ * Get the xscaling factor of this matrix.
+ * @return The x-scale.
+ */
+ public float getXScale()
+ {
+ float xScale = single[0];
+
+ /**
+ * BM: if the trm is rotated, the calculation is a little more complicated
+ *
+ * The rotation matrix multiplied with the scaling matrix is:
+ * ( x 0 0) ( cos sin 0) ( x*cos x*sin 0)
+ * ( 0 y 0) * (-sin cos 0) = (-y*sin y*cos 0)
+ * ( 0 0 1) ( 0 0 1) ( 0 0 1)
+ *
+ * So, if you want to deduce x from the matrix you take
+ * M(0,0) = x*cos and M(0,1) = x*sin and use the theorem of Pythagoras
+ *
+ * sqrt(M(0,0)^2+M(0,1)^2) =
+ * sqrt(x2*cos2+x2*sin2) =
+ * sqrt(x2*(cos2+sin2)) = <- here is the trick cos2+sin2 is one
+ * sqrt(x2) =
+ * abs(x)
+ */
+ if( !(single[1]==0.0f && single[3]==0.0f) )
+ {
+ xScale = (float)Math.sqrt(Math.pow(single[0], 2)+
+ Math.pow(single[1], 2));
+ }
+ return xScale;
+ }
+
+ /**
+ * Get the y scaling factor of this matrix.
+ * @return The y-scale factor.
+ */
+ public float getYScale()
+ {
+ float yScale = single[4];
+ if( !(single[1]==0.0f && single[3]==0.0f) )
+ {
+ yScale = (float)Math.sqrt(Math.pow(single[3], 2)+
+ Math.pow(single[4], 2));
+ }
+ return yScale;
+ }
+
+ /**
+ * Get the x position in the matrix.
+ * @return The x-position.
+ */
+ public float getXPosition()
+ {
+ return single[6];
+ }
+
+ /**
+ * Get the y position.
+ * @return The y position.
+ */
+ public float getYPosition()
+ {
+ return single[7];
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/PDFHighlighter.java b/src/main/java/org/pdfbox/util/PDFHighlighter.java
new file mode 100644
index 0000000..6c27225
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/PDFHighlighter.java
@@ -0,0 +1,213 @@
+package org.pdfbox.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.pdfbox.pdmodel.PDDocument;
+import org.pdfbox.pdmodel.PDPage;
+
+
+/**
+ * Highlighting of words in a PDF document with an XML file.
+ *
+ * @author slagraulet (slagraulet@cardiweb.com)
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.6 $
+ *
+ * @see <a href="http://partners.adobe.com/public/developer/en/pdf/HighlightFileFormat.pdf">
+ * Adobe Highlight File Format</a>
+ */
+public class PDFHighlighter extends PDFTextStripper
+{
+ private Writer highlighterOutput = null;
+ //private Color highlightColor = Color.YELLOW;
+
+ private String[] searchedWords;
+ private ByteArrayOutputStream textOS = null;
+ private Writer textWriter = null;
+
+ /**
+ * Default constructor.
+ *
+ * @throws IOException If there is an error constructing this class.
+ */
+ public PDFHighlighter() throws IOException
+ {
+ super();
+ super.setLineSeparator( "" );
+ super.setPageSeparator( "" );
+ super.setWordSeparator( "" );
+ super.setShouldSeparateByBeads( false );
+ super.setSuppressDuplicateOverlappingText( false );
+ }
+
+ /**
+ * Generate an XML highlight string based on the PDF.
+ *
+ * @param pdDocument The PDF to find words in.
+ * @param highlightWord The word to search for.
+ * @param xmlOutput The resulting output xml file.
+ *
+ * @throws IOException If there is an error reading from the PDF, or writing to the XML.
+ */
+ public void generateXMLHighlight(PDDocument pdDocument, String highlightWord, Writer xmlOutput ) throws IOException
+ {
+ generateXMLHighlight( pdDocument, new String[] { highlightWord }, xmlOutput );
+ }
+
+ /**
+ * Generate an XML highlight string based on the PDF.
+ *
+ * @param pdDocument The PDF to find words in.
+ * @param sWords The words to search for.
+ * @param xmlOutput The resulting output xml file.
+ *
+ * @throws IOException If there is an error reading from the PDF, or writing to the XML.
+ */
+ public void generateXMLHighlight(PDDocument pdDocument, String[] sWords, Writer xmlOutput ) throws IOException
+ {
+ highlighterOutput = xmlOutput;
+ searchedWords = sWords;
+ highlighterOutput.write("<XML>\n<Body units=characters " +
+ //color and mode are not implemented by the highlight spec
+ //so don't include them for now
+ //" color=#" + getHighlightColorAsString() +
+ //" mode=active " + */
+ " version=2>\n<Highlight>\n");
+ textOS = new ByteArrayOutputStream();
+ textWriter = new OutputStreamWriter( textOS, "UTF-16" );
+ writeText(pdDocument, textWriter);
+ highlighterOutput.write("</Highlight>\n</Body>\n</XML>");
+ highlighterOutput.flush();
+ }
+
+ /**
+ * @see PDFTextStripper#endPage( PDPage )
+ */
+ protected void endPage( PDPage pdPage ) throws IOException
+ {
+ textWriter.flush();
+
+ String page = new String( textOS.toByteArray(), "UTF-16" );
+ textOS.reset();
+ //page = page.replaceAll( "\n", "" );
+ //page = page.replaceAll( "\r", "" );
+ //page = CCRStringUtil.stripChar(page, '\n');
+ //page = CCRStringUtil.stripChar(page, '\r');
+
+ // Traitement des listes à puces (caractères spéciaux)
+ if (page.indexOf("a") != -1)
+ {
+ page = page.replaceAll("a[0-9]{1,3}", ".");
+ }
+
+ for (int i = 0; i < searchedWords.length; i++)
+ {
+ Pattern pattern = Pattern.compile(searchedWords[i], Pattern.CASE_INSENSITIVE);
+ Matcher matcher = pattern.matcher(page);
+ while( matcher.find() )
+ {
+ int begin = matcher.start();
+ int end = matcher.end();
+ highlighterOutput.write(" <loc " +
+ "pg=" + (getCurrentPageNo()-1)
+ + " pos=" + begin
+ + " len="+ (end - begin)
+ + ">\n");
+ }
+ }
+ }
+
+ /**
+ * Command line application.
+ *
+ * @param args The command line arguments to the application.
+ *
+ * @throws IOException If there is an error generating the highlight file.
+ */
+ public static void main(String[] args) throws IOException
+ {
+ PDFHighlighter xmlExtractor = new PDFHighlighter();
+ PDDocument doc = null;
+ try
+ {
+ if( args.length < 2 )
+ {
+ usage();
+ }
+ String[] highlightStrings = new String[ args.length - 1];
+ System.arraycopy( args, 1, highlightStrings, 0, highlightStrings.length );
+ doc = PDDocument.load( args[0] );
+
+ xmlExtractor.generateXMLHighlight(
+ doc,
+ highlightStrings,
+ new OutputStreamWriter( System.out ) );
+ }
+ finally
+ {
+ if( doc != null )
+ {
+ doc.close();
+ }
+ }
+ }
+
+ private static void usage()
+ {
+ System.err.println( "usage: java " + PDFHighlighter.class.getName() + " <pdf file> word1 word2 word3 ..." );
+ System.exit( 1 );
+ }
+
+
+ /**
+ * Get the color to highlight the strings with. Default is Color.YELLOW.
+ *
+ * @return The color to highlight strings with.
+ */
+ /*public Color getHighlightColor()
+ {
+ return highlightColor;
+ }**/
+
+ /**
+ * Get the color to highlight the strings with. Default is Color.YELLOW.
+ *
+ * @param color The color to highlight strings with.
+ */
+ /*public void setHighlightColor(Color color)
+ {
+ this.highlightColor = color;
+ }**/
+
+ /**
+ * Set the highlight color using HTML like rgb string. The string must be 6 characters long.
+ *
+ * @param color The color to use for highlighting. Should be in the format of "FF0000".
+ */
+ /*public void setHighlightColor( String color )
+ {
+ highlightColor = Color.decode( color );
+ }**/
+
+ /**
+ * Get the highlight color as an HTML like string. This will return a string of six characters.
+ *
+ * @return The current highlight color. For example FF0000
+ */
+ /*public String getHighlightColorAsString()
+ {
+ //BJL: kudos to anyone that has a cleaner way of doing this!
+ String red = Integer.toHexString( highlightColor.getRed() );
+ String green = Integer.toHexString( highlightColor.getGreen() );
+ String blue = Integer.toHexString( highlightColor.getBlue() );
+
+ return (red.length() < 2 ? "0" + red : red) +
+ (green.length() < 2 ? "0" + green : green) +
+ (blue.length() < 2 ? "0" + blue : blue);
+ }**/
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/PDFOperator.java b/src/main/java/org/pdfbox/util/PDFOperator.java
new file mode 100644
index 0000000..76d9887
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/PDFOperator.java
@@ -0,0 +1,153 @@
+/**
+ * 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.util;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class represents an Operator in the content stream.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.13 $
+ */
+public class PDFOperator
+{
+ private String theOperator;
+ private byte[] imageData;
+ private ImageParameters imageParameters;
+
+ private static Map operators = Collections.synchronizedMap( new HashMap() );
+
+ /**
+ * Constructor.
+ *
+ * @param aOperator The operator that this object will represent.
+ */
+ private PDFOperator( String aOperator )
+ {
+ theOperator = aOperator;
+ if( aOperator.startsWith( "/" ) )
+ {
+ throw new RuntimeException( "Operators are not allowed to start with / '" + aOperator + "'" );
+ }
+ }
+
+ /**
+ * This is used to create/cache operators in the system.
+ *
+ * @param operator The operator for the system.
+ *
+ * @return The operator that matches the operator keyword.
+ */
+ public static PDFOperator getOperator( String operator )
+ {
+ PDFOperator operation = null;
+ if( operator.equals( "ID" ) || operator.equals( "BI" ) )
+ {
+ //we can't cache the ID operators.
+ operation = new PDFOperator( operator );
+ }
+ else
+ {
+ operation = (PDFOperator)operators.get( operator );
+ if( operation == null )
+ {
+ operation = new PDFOperator( operator );
+ operators.put( operator, operation );
+ }
+ }
+
+ return operation;
+ }
+
+ /**
+ * This will get the operation that this operator represents.
+ *
+ * @return The string representation of the operation.
+ */
+ public String getOperation()
+ {
+ return theOperator;
+ }
+
+ /**
+ * This will print a string rep of this class.
+ *
+ * @return A string rep of this class.
+ */
+ public String toString()
+ {
+ return "PDFOperator{" + theOperator + "}";
+ }
+
+ /**
+ * This is the special case for the ID operator where there are just random
+ * bytes inlined the stream.
+ *
+ * @return Value of property imageData.
+ */
+ public byte[] getImageData()
+ {
+ return this.imageData;
+ }
+
+ /**
+ * This will set the image data, this is only used for the ID operator.
+ *
+ * @param imageDataArray New value of property imageData.
+ */
+ public void setImageData(byte[] imageDataArray)
+ {
+ imageData = imageDataArray;
+ }
+
+ /**
+ * This will get the image parameters, this is only valid for BI operators.
+ *
+ * @return The image parameters.
+ */
+ public ImageParameters getImageParameters()
+ {
+ return imageParameters;
+ }
+
+ /**
+ * This will set the image parameters, this is only valid for BI operators.
+ *
+ * @param params The image parameters.
+ */
+ public void setImageParameters( ImageParameters params)
+ {
+ imageParameters = params;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/PDFStreamEngine.java b/src/main/java/org/pdfbox/util/PDFStreamEngine.java
new file mode 100644
index 0000000..1e05f8a
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/PDFStreamEngine.java
@@ -0,0 +1,622 @@
+/**
+ * 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.util;
+
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Stack;
+
+import org.pdfbox.cos.COSObject;
+import org.pdfbox.cos.COSStream;
+import org.pdfbox.exceptions.WrappedIOException;
+
+import org.pdfbox.pdmodel.PDPage;
+import org.pdfbox.pdmodel.PDResources;
+
+import org.pdfbox.pdmodel.font.PDFont;
+
+import org.pdfbox.pdmodel.graphics.PDGraphicsState;
+
+import org.pdfbox.util.operator.OperatorProcessor;
+
+import org.apache.log4j.Logger;
+
+/**
+ * This class will run through a PDF content stream and execute certain operations
+ * and provide a callback interface for clients that want to do things with the stream.
+ * See the PDFTextStripper class for an example of how to use this class.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.29 $
+ */
+public class PDFStreamEngine
+{
+ private static Logger log = Logger.getLogger(PDFStreamEngine.class);
+
+ static protected final byte[] SPACE_BYTES = { (byte)32 };
+
+ private PDGraphicsState graphicsState = null;
+
+ protected Matrix textMatrix = null;
+ protected Matrix textLineMatrix = null;
+ protected Stack graphicsStack = new Stack();
+ //private PDResources resources = null;
+
+ protected Map operators = new HashMap();
+
+ protected Map fontToAverageWidths = new HashMap();
+
+ protected Stack streamResourcesStack = new Stack();
+
+ protected PDPage page;
+
+ /**
+ * This is a simple internal class used by the Stream engine to handle the
+ * resources stack.
+ */
+ protected static class StreamResources
+ {
+ protected Map fonts;
+ protected Map colorSpaces;
+ protected Map xobjects;
+ protected Map graphicsStates;
+ protected PDResources resources;
+ }
+
+ /**
+ * Constructor.
+ */
+ public PDFStreamEngine()
+ {
+ //default constructor
+ }
+
+ /**
+ * Constructor with engine properties. The property keys are all
+ * PDF operators, the values are class names used to execute those
+ * operators.
+ *
+ * @param properties The engine properties.
+ *
+ * @throws IOException If there is an error setting the engine properties.
+ */
+ public PDFStreamEngine( Properties properties ) throws IOException
+ {
+ try
+ {
+ Iterator keys = properties.keySet().iterator();
+ while( keys.hasNext() )
+ {
+ String operator = (String)keys.next();
+ String operatorClass = properties.getProperty( operator );
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "Operator Class: " + operator + "=" + operatorClass );
+ }
+ OperatorProcessor op = (OperatorProcessor)Class.forName( operatorClass ).newInstance();
+ op.setContext( this );
+ operators.put( operator, op );
+ }
+ }
+ catch( Exception e )
+ {
+ throw new WrappedIOException( e );
+ }
+ }
+
+ /**
+ * This will process the contents of the stream.
+ *
+ * @param aPage The page.
+ * @param resources The location to retrieve resources.
+ * @param cosStream the Stream to execute.
+ *
+ *
+ * @throws IOException if there is an error accessing the stream.
+ */
+ public void processStream( PDPage aPage, PDResources resources, COSStream cosStream ) throws IOException
+ {
+ graphicsState = new PDGraphicsState();
+ textMatrix = null;
+ textLineMatrix = null;
+ graphicsStack.clear();
+ streamResourcesStack.clear();
+ fontToAverageWidths.clear();
+
+ processSubStream( aPage, resources, cosStream );
+ }
+
+ /**
+ * Process a sub stream of the current stream.
+ *
+ * @param aPage The page used for drawing.
+ * @param resources The resources used when processing the stream.
+ * @param cosStream The stream to process.
+ *
+ * @throws IOException If there is an exception while processing the stream.
+ */
+ public void processSubStream( PDPage aPage, PDResources resources, COSStream cosStream ) throws IOException
+ {
+ page = aPage;
+ if( resources != null )
+ {
+ StreamResources sr = new StreamResources();
+ sr.fonts = resources.getFonts();
+ sr.colorSpaces = resources.getColorSpaces();
+ sr.xobjects = resources.getXObjects();
+ sr.graphicsStates = resources.getGraphicsStates();
+ sr.resources = resources;
+ streamResourcesStack.push(sr);
+ }
+ try
+ {
+ List arguments = new ArrayList();
+ long startTokens = System.currentTimeMillis();
+ List tokens = cosStream.getStreamTokens();
+ long stopTokens = System.currentTimeMillis();
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "Getting tokens time=" + (stopTokens-startTokens) );
+ }
+ if( tokens != null )
+ {
+ Iterator iter = tokens.iterator();
+ while( iter.hasNext() )
+ {
+ Object next = iter.next();
+ if( next instanceof COSObject )
+ {
+ arguments.add( ((COSObject)next).getObject() );
+ }
+ else if( next instanceof PDFOperator )
+ {
+ processOperator( (PDFOperator)next, arguments );
+ arguments = new ArrayList();
+ }
+ else
+ {
+ arguments.add( next );
+ }
+ }
+ }
+ }
+ finally
+ {
+ if( resources != null )
+ {
+ streamResourcesStack.pop();
+ }
+ }
+
+ }
+
+ /**
+ * A method provided as an event interface to allow a subclass to perform
+ * some specific functionality when a character needs to be displayed.
+ *
+ * @param text The character to be displayed.
+ */
+ protected void showCharacter( TextPosition text )
+ {
+ //subclasses can override to provide specific functionality.
+ }
+
+ /**
+ * You should override this method if you want to perform an action when a
+ * string is being shown.
+ *
+ * @param string The string to display.
+ *
+ * @throws IOException If there is an error showing the string
+ */
+ public void showString( byte[] string ) throws IOException
+ {
+ float spaceWidth = 0;
+ float spacing = 0;
+ StringBuffer stringResult = new StringBuffer(string.length);
+
+ float characterDisplacement = 0;
+ float spaceDisplacement = 0;
+ float fontSize = graphicsState.getTextState().getFontSize();
+ float horizontalScaling = graphicsState.getTextState().getHorizontalScalingPercent()/100f;
+ float rise = graphicsState.getTextState().getRise();
+ final float wordSpacing = graphicsState.getTextState().getWordSpacing();
+ final float characterSpacing = graphicsState.getTextState().getCharacterSpacing();
+ float wordSpacingDisplacement = 0;
+
+ PDFont font = graphicsState.getTextState().getFont();
+
+ //This will typically be 1000 but in the case of a type3 font
+ //this might be a different number
+ float glyphSpaceToTextSpaceFactor = 1f/font.getFontMatrix().getValue( 0, 0 );
+ Float averageWidth = (Float)fontToAverageWidths.get( font );
+ if( averageWidth == null )
+ {
+ averageWidth = new Float( font.getAverageFontWidth() );
+ fontToAverageWidths.put( font, averageWidth );
+ }
+
+ Matrix initialMatrix = new Matrix();
+ initialMatrix.setValue(0,0,1);
+ initialMatrix.setValue(0,1,0);
+ initialMatrix.setValue(0,2,0);
+ initialMatrix.setValue(1,0,0);
+ initialMatrix.setValue(1,1,1);
+ initialMatrix.setValue(1,2,0);
+ initialMatrix.setValue(2,0,0);
+ initialMatrix.setValue(2,1,rise);
+ initialMatrix.setValue(2,2,1);
+
+
+ //this
+ int codeLength = 1;
+ Matrix ctm = graphicsState.getCurrentTransformationMatrix();
+
+ //lets see what the space displacement should be
+ spaceDisplacement = (font.getFontWidth( SPACE_BYTES, 0, 1 )/glyphSpaceToTextSpaceFactor);
+ if( spaceDisplacement == 0 )
+ {
+ spaceDisplacement = (averageWidth.floatValue()/glyphSpaceToTextSpaceFactor);
+ //The average space width appears to be higher than necessary
+ //so lets make it a little bit smaller.
+ spaceDisplacement *= .80f;
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "Font: Space From Average=" + spaceDisplacement );
+ }
+ }
+ int pageRotation = page.findRotation();
+ Matrix trm = initialMatrix.multiply( textMatrix ).multiply( ctm );
+ float x = trm.getValue(2,0);
+ float y = trm.getValue(2,1);
+ if( pageRotation == 0 )
+ {
+ trm.setValue( 2,1, -y + page.findMediaBox().getHeight() );
+ }
+ else if( pageRotation == 90 )
+ {
+ trm.setValue( 2,0, y );
+ trm.setValue( 2,1, x );
+ }
+ else if( pageRotation == 270 )
+ {
+ trm.setValue( 2,0, -y + page.findMediaBox().getHeight() );
+ trm.setValue( 2,1, x );
+ }
+ for( int i=0; i<string.length; i+=codeLength )
+ {
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "initialMatrix=" + initialMatrix );
+ log.debug( "textMatrix=" + textMatrix );
+ log.debug( "initialMatrix.multiply( textMatrix )=" + initialMatrix.multiply( textMatrix ) );
+ log.debug( "ctm=" + ctm );
+ log.debug( "trm=" + initialMatrix.multiply( textMatrix ).multiply( ctm ) );
+ }
+ codeLength = 1;
+
+ String c = font.encode( string, i, codeLength );
+
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "Character Code=" + string[i] + "='" + c + "'" );
+ }
+ if( c == null && i+1<string.length)
+ {
+ //maybe a multibyte encoding
+ codeLength++;
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "Multibyte Character Code=" + string[i] + string[i+1] );
+ }
+ c = font.encode( string, i, codeLength );
+ }
+ stringResult.append( c );
+
+ //todo, handle horizontal displacement
+ characterDisplacement += (font.getFontWidth( string, i, codeLength )/glyphSpaceToTextSpaceFactor);
+
+
+ // PDF Spec - 5.5.2 Word Spacing
+ //
+ // Word spacing works the same was as character spacing, but applies
+ // only to the space character, code 32.
+ //
+ // Note: Word spacing is applied to every occurrence of the single-byte
+ // character code 32 in a string. This can occur when using a simple
+ // font or a composite font that defines code 32 as a single-byte code.
+ // It does not apply to occurrences of the byte value 32 in multiple-byte
+ // codes.
+ //
+ // RDD - My interpretation of this is that only character code 32's that
+ // encode to spaces should have word spacing applied. Cases have been
+ // observed where a font has a space character with a character code
+ // other than 32, and where word spacing (Tw) was used. In these cases,
+ // applying word spacing to either the non-32 space or to the character
+ // code 32 non-space resulted in errors consistent with this interpretation.
+ //
+
+ boolean withCS = false;
+ if( (string[i] == 0x20) && c.equals( " " ) )
+ {
+ spacing += wordSpacing + characterSpacing;
+ withCS = true;
+ }
+ else
+ {
+ spacing += characterSpacing;
+ }
+
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "Checking code '" + c + "' font=" + graphicsState.getTextState().getFont() +
+ " Tc=" + characterSpacing +
+ " Tw=" + wordSpacing +
+ " fontSize=" + fontSize +
+ " horizontalScaling=" + horizontalScaling +
+ " totalDisp=" + characterDisplacement +
+ " spacing=" + spacing + "(" + withCS + ")" );
+ }
+ // We want to update the textMatrix using the width, in text space units.
+ //
+
+ }
+
+ //The adjustment will always be zero. The adjustment as shown in the
+ //TJ operator will be handled separately.
+ float adjustment=0;
+ //todo, need to compute the horizontal displacement
+ float ty = 0;
+ float tx = ((characterDisplacement-adjustment/glyphSpaceToTextSpaceFactor)*fontSize + spacing)
+ *horizontalScaling;
+
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "disp=" + characterDisplacement + " adj=" + adjustment +
+ " fSize=" + fontSize + " tx=" + tx );
+ }
+
+ float xScale = trm.getXScale();
+ float yScale = trm.getYScale();
+ float xPos = trm.getXPosition();
+ float yPos = trm.getYPosition();
+ spaceWidth = spaceDisplacement * xScale * fontSize;
+ wordSpacingDisplacement = wordSpacing*xScale * fontSize;
+ Matrix td = new Matrix();
+ td.setValue( 2, 0, tx );
+ td.setValue( 2, 1, ty );
+
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "TRM=" + trm );
+ log.debug( "TextMatrix before " + textMatrix );
+ }
+ float xPosBefore = textMatrix.getXPosition();
+ float yPosBefore = textMatrix.getYPosition();
+ textMatrix = td.multiply( textMatrix );
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "TextMatrix after " + textMatrix );
+ }
+ float totalStringDisplacement = 0;
+ if( pageRotation == 0 )
+ {
+ totalStringDisplacement = (textMatrix.getXPosition() - xPosBefore);
+ }
+ else if( pageRotation == 90 )
+ {
+ totalStringDisplacement = (textMatrix.getYPosition() - yPosBefore);
+ }
+ else if( pageRotation == 270 )
+ {
+ totalStringDisplacement = (yPosBefore - textMatrix.getYPosition());
+ }
+ showCharacter(
+ new TextPosition(
+ xPos,
+ yPos,
+ xScale,
+ yScale,
+ totalStringDisplacement,
+ spaceWidth,
+ stringResult.toString(),
+ graphicsState.getTextState().getFont(),
+ graphicsState.getTextState().getFontSize(),
+ wordSpacingDisplacement ));
+ }
+
+ /**
+ * This is used to handle an operation.
+ *
+ * @param operation The operation to perform.
+ * @param arguments The list of arguments.
+ *
+ * @throws IOException If there is an error processing the operation.
+ */
+ public void processOperator( String operation, List arguments ) throws IOException
+ {
+ PDFOperator oper = PDFOperator.getOperator( operation );
+ processOperator( oper, arguments );
+ }
+
+ /**
+ * 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
+ {
+ String operation = operator.getOperation();
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "processOperator( '" + operation + "' )" );
+ }
+ OperatorProcessor processor = (OperatorProcessor)operators.get( operation );
+ if( processor != null )
+ {
+ processor.process( operator, arguments );
+ }
+ }
+
+ /**
+ * @return Returns the colorSpaces.
+ */
+ public Map getColorSpaces()
+ {
+ return ((StreamResources) streamResourcesStack.peek()).colorSpaces;
+ }
+
+ /**
+ * @return Returns the colorSpaces.
+ */
+ public Map getXObjects()
+ {
+ return ((StreamResources) streamResourcesStack.peek()).xobjects;
+ }
+
+ /**
+ * @param value The colorSpaces to set.
+ */
+ public void setColorSpaces(Map value)
+ {
+ ((StreamResources) streamResourcesStack.peek()).colorSpaces = value;
+ }
+ /**
+ * @return Returns the fonts.
+ */
+ public Map getFonts()
+ {
+ return ((StreamResources) streamResourcesStack.peek()).fonts;
+ }
+ /**
+ * @param value The fonts to set.
+ */
+ public void setFonts(Map value)
+ {
+ ((StreamResources) streamResourcesStack.peek()).fonts = value;
+ }
+ /**
+ * @return Returns the graphicsStack.
+ */
+ public Stack getGraphicsStack()
+ {
+ return graphicsStack;
+ }
+ /**
+ * @param value The graphicsStack to set.
+ */
+ public void setGraphicsStack(Stack value)
+ {
+ graphicsStack = value;
+ }
+ /**
+ * @return Returns the graphicsState.
+ */
+ public PDGraphicsState getGraphicsState()
+ {
+ return graphicsState;
+ }
+ /**
+ * @param value The graphicsState to set.
+ */
+ public void setGraphicsState(PDGraphicsState value)
+ {
+ graphicsState = value;
+ }
+ /**
+ * @return Returns the graphicsStates.
+ */
+ public Map getGraphicsStates()
+ {
+ return ((StreamResources) streamResourcesStack.peek()).graphicsStates;
+ }
+ /**
+ * @param value The graphicsStates to set.
+ */
+ public void setGraphicsStates(Map value)
+ {
+ ((StreamResources) streamResourcesStack.peek()).graphicsStates = value;
+ }
+ /**
+ * @return Returns the textLineMatrix.
+ */
+ public Matrix getTextLineMatrix()
+ {
+ return textLineMatrix;
+ }
+ /**
+ * @param value The textLineMatrix to set.
+ */
+ public void setTextLineMatrix(Matrix value)
+ {
+ textLineMatrix = value;
+ }
+ /**
+ * @return Returns the textMatrix.
+ */
+ public Matrix getTextMatrix()
+ {
+ return textMatrix;
+ }
+ /**
+ * @param value The textMatrix to set.
+ */
+ public void setTextMatrix(Matrix value)
+ {
+ textMatrix = value;
+ }
+ /**
+ * @return Returns the resources.
+ */
+ public PDResources getResources()
+ {
+ return ((StreamResources) streamResourcesStack.peek()).resources;
+ }
+
+ /**
+ * Get the current page that is being processed.
+ *
+ * @return The page being processed.
+ */
+ public PDPage getCurrentPage()
+ {
+ return page;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/PDFText2HTML.java b/src/main/java/org/pdfbox/util/PDFText2HTML.java
new file mode 100644
index 0000000..0409eaa
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/PDFText2HTML.java
@@ -0,0 +1,271 @@
+/**
+ * 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.util;
+
+import java.io.IOException;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.pdfbox.pdmodel.PDDocument;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Wrap stripped text in simple HTML, trying to form HTML paragraphs.
+ * Paragraphs broken by pages, columns, or figures are not mended.
+ *
+ *
+ * @author jjb - http://www.johnjbarton.com
+ * @version $Revision: 1.1 $
+ *
+ */
+public class PDFText2HTML extends PDFTextStripper
+{
+ private static Logger log = Logger.getLogger(PDFText2HTML.class);
+ private static final int INITIAL_PDF_TO_HTML_BYTES = 8192;
+
+ private TextPosition beginTitle;
+ private TextPosition afterEndTitle;
+ private String titleGuess;
+ private boolean suppressParagraphs;
+ private boolean onFirstPage = true;
+
+ /**
+ * Constructor.
+ *
+ * @throws IOException If there is an error during initialization.
+ */
+ public PDFText2HTML() throws IOException
+ {
+ titleGuess = "";
+ beginTitle = null;
+ afterEndTitle = null;
+ suppressParagraphs = false;
+ }
+
+ /**
+ * Write the header to the output document.
+ *
+ * @throws IOException If there is a problem writing out the header to the document.
+ */
+ protected void writeHeader() throws IOException
+ {
+ StringBuffer buf = new StringBuffer(INITIAL_PDF_TO_HTML_BYTES);
+ buf.append("<html><head>");
+ buf.append("<title>");
+ buf.append(getTitleGuess());
+ buf.append("</title>");
+ buf.append("</head>");
+ buf.append("<body>\n");
+ getOutput().write(buf.toString());
+ }
+
+ /**
+ * The guess to the document title.
+ *
+ * @return A string that is the title of this document.
+ */
+ protected String getTitleGuess()
+ {
+ return titleGuess;
+ }
+
+ /**
+ * @see PDFTextStripper#flushText
+ */
+ protected void flushText() throws IOException
+ {
+ Iterator textIter = getCharactersByArticle().iterator();
+
+ if (onFirstPage)
+ {
+ guessTitle(textIter);
+ writeHeader();
+ onFirstPage = false;
+ }
+ super.flushText();
+ }
+
+ /**
+ * @see PDFTextStripper#endDocument( PDDocument )
+ */
+ public void endDocument(PDDocument pdf) throws IOException
+ {
+ output.write("</body></html>");
+ }
+
+ /**
+ * This method will attempt to guess the title of the document.
+ *
+ * @param textIter The characters on the first page.
+ * @return The text position that is guessed to be the title.
+ */
+ protected TextPosition guessTitle(Iterator textIter)
+ {
+ float lastFontSize = -1.0f;
+ int stringsInFont = 0;
+ StringBuffer titleText = new StringBuffer();
+ while (textIter.hasNext())
+ {
+ Iterator textByArticle = ((List)textIter.next()).iterator();
+ while( textByArticle.hasNext() )
+ {
+ TextPosition position = (TextPosition) textByArticle.next();
+ float currentFontSize = position.getFontSize();
+ if (currentFontSize != lastFontSize)
+ {
+ if (beginTitle != null)
+ { // font change in candidate title.
+ if (stringsInFont == 0)
+ {
+ beginTitle = null; // false alarm
+ titleText.setLength(0);
+ }
+ else
+ {
+ // had a significant font with some words: call it a title
+ titleGuess = titleText.toString();
+ log.debug("Title candidate =" + titleGuess);
+ afterEndTitle = position;
+ return beginTitle;
+ }
+ }
+ else
+ { // font change and begin == null
+ if (currentFontSize > 13.0f)
+ { // most body text is 12pt max I guess
+ beginTitle = position;
+ }
+ }
+
+ lastFontSize = currentFontSize;
+ stringsInFont = 0;
+ }
+ stringsInFont++;
+ if (beginTitle != null)
+ {
+ titleText.append(position.getCharacter()+" ");
+ }
+ }
+ }
+ return beginTitle; // null
+ }
+
+ /**
+ * Write out the paragraph separator.
+ *
+ * @throws IOException If there is an error writing to the stream.
+ */
+ protected void startParagraph() throws IOException
+ {
+ if (! suppressParagraphs)
+ {
+ getOutput().write("<p>");
+ }
+ }
+ /**
+ * Write out the paragraph separator.
+ *
+ * @throws IOException If there is an error writing to the stream.
+ */
+ protected void endParagraph() throws IOException
+ {
+ if (! suppressParagraphs)
+ {
+ getOutput().write("</p>");
+ }
+ }
+
+ /**
+ * @see PDFTextStripper#writeCharacters( TextPosition )
+ */
+ protected void writeCharacters(TextPosition position ) throws IOException
+ {
+ if (position == beginTitle)
+ {
+ output.write("<H1>");
+ suppressParagraphs = true;
+ }
+ if (position == afterEndTitle)
+ {
+ output.write("</H1>"); // end title and start first paragraph
+ suppressParagraphs = false;
+ }
+
+ String chars = position.getCharacter();
+
+ for (int i = 0; i < chars.length(); i++)
+ {
+ char c = chars.charAt(i);
+ if ((c < 32) || (c > 126))
+ {
+ int charAsInt = c;
+ output.write("&#" + charAsInt + ";");
+ }
+ else
+ {
+ switch (c)
+ {
+ case 34:
+ output.write("&quot;");
+ break;
+ case 38:
+ output.write("&amp;");
+ break;
+ case 60:
+ output.write("&lt;");
+ break;
+ case 62:
+ output.write("&gt;");
+ break;
+ default:
+ output.write(c);
+ }
+ }
+ }
+ }
+
+ /**
+ * @return Returns the suppressParagraphs.
+ */
+ public boolean isSuppressParagraphs()
+ {
+ return suppressParagraphs;
+ }
+ /**
+ * @param shouldSuppressParagraphs The suppressParagraphs to set.
+ */
+ public void setSuppressParagraphs(boolean shouldSuppressParagraphs)
+ {
+ this.suppressParagraphs = shouldSuppressParagraphs;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/PDFTextStripper.java b/src/main/java/org/pdfbox/util/PDFTextStripper.java
new file mode 100644
index 0000000..56e80cc
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/PDFTextStripper.java
@@ -0,0 +1,1033 @@
+/**
+ * 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.util;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.pdfbox.cos.COSDocument;
+import org.pdfbox.cos.COSStream;
+
+import org.pdfbox.pdmodel.PDDocument;
+import org.pdfbox.pdmodel.PDPage;
+
+import org.pdfbox.pdmodel.common.PDRectangle;
+import org.pdfbox.pdmodel.common.PDStream;
+
+import org.pdfbox.pdmodel.encryption.PDEncryptionDictionary;
+import org.pdfbox.pdmodel.encryption.PDStandardEncryption;
+import org.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
+import org.pdfbox.pdmodel.interactive.pagenavigation.PDThreadBead;
+
+import org.pdfbox.exceptions.CryptographyException;
+import org.pdfbox.exceptions.InvalidPasswordException;
+
+import org.apache.log4j.Logger;
+
+
+/**
+ * This class will take a pdf document and strip out all of the text and ignore the
+ * formatting and such.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.62 $
+ */
+public class PDFTextStripper extends PDFStreamEngine
+{
+ private static Logger log = Logger.getLogger(PDFTextStripper.class);
+
+ private int currentPageNo = 0;
+ private int startPage = 1;
+ private int endPage = Integer.MAX_VALUE;
+ private PDOutlineItem startBookmark = null;
+ private int startBookmarkPageNumber = -1;
+ private PDOutlineItem endBookmark = null;
+ private int endBookmarkPageNumber = -1;
+ private PDDocument document;
+ private boolean suppressDuplicateOverlappingText = true;
+ private boolean shouldSeparateByBeads = true;
+ private boolean sortByPosition = false;
+
+ private List pageArticles = null;
+ /**
+ * The charactersByArticle is used to extract text by article divisions. For example
+ * a PDF that has two columns like a newspaper, we want to extract the first column and
+ * then the second column. In this example the PDF would have 2 beads(or articles), one for
+ * each column. The size of the charactersByArticle would be 5, because not all text on the
+ * screen will fall into one of the articles. The five divisions are shown below
+ *
+ * Text before first article
+ * first article text
+ * text between first article and second article
+ * second article text
+ * text after second article
+ *
+ * Most PDFs won't have any beads, so charactersByArticle will contain a single entry.
+ */
+ protected Vector charactersByArticle = new Vector();
+
+ private Map characterListMapping = new HashMap();
+
+ private String lineSeparator = System.getProperty("line.separator");
+ private String pageSeparator = System.getProperty("line.separator");
+ private String wordSeparator = " ";
+
+ /**
+ * The stream to write the output to.
+ */
+ protected Writer output;
+
+ /**
+ * Instantiate a new PDFTextStripper object. This object will load properties from
+ * Resources/PDFTextStripper.properties.
+ * @throws IOException If there is an error loading the properties.
+ */
+ public PDFTextStripper() throws IOException
+ {
+ super( ResourceLoader.loadProperties( "Resources/PDFTextStripper.properties" ) );
+ }
+
+ /**
+ * This will return the text of a document. See writeText. <br />
+ * NOTE: The document must not be encrypted when coming into this method.
+ *
+ * @param doc The document to get the text from.
+ *
+ * @return The text of the PDF document.
+ *
+ * @throws IOException if the doc state is invalid or it is encrypted.
+ */
+ public String getText( PDDocument doc ) throws IOException
+ {
+ StringWriter outputStream = new StringWriter();
+ writeText( doc, outputStream );
+ return outputStream.toString();
+ }
+
+ /**
+ * @deprecated
+ * @see PDFTextStripper#getText( PDDocument )
+ * @param doc The document to extract the text from.
+ * @return The document text.
+ * @throws IOException If there is an error extracting the text.
+ */
+ public String getText( COSDocument doc ) throws IOException
+ {
+ return getText( new PDDocument( doc ) );
+ }
+
+ /**
+ * @deprecated
+ * @see PDFTextStripper#writeText( PDDocument, Writer )
+ * @param doc The document to extract the text.
+ * @param outputStream The stream to write the text to.
+ * @throws IOException If there is an error extracting the text.
+ */
+ public void writeText( COSDocument doc, Writer outputStream ) throws IOException
+ {
+ writeText( new PDDocument( doc ), outputStream );
+ }
+
+ /**
+ * This will take a PDDocument and write the text of that document to the print writer.
+ *
+ * @param doc The document to get the data from.
+ * @param outputStream The location to put the text.
+ *
+ * @throws IOException If the doc is in an invalid state.
+ */
+ public void writeText( PDDocument doc, Writer outputStream ) throws IOException
+ {
+
+ PDEncryptionDictionary encDictionary = doc.getEncryptionDictionary();
+
+ //only care about standard encryption and if it was decrypted with the
+ //user password
+ if( encDictionary instanceof PDStandardEncryption &&
+ !doc.wasDecryptedWithOwnerPassword() )
+ {
+ PDStandardEncryption stdEncryption = (PDStandardEncryption)encDictionary;
+ if( !stdEncryption.canExtractContent() )
+ {
+ throw new IOException( "You do not have permission to extract text" );
+ }
+ }
+ currentPageNo = 0;
+ document = doc;
+ output = outputStream;
+ startDocument(document);
+
+ if( document.isEncrypted() )
+ {
+ // We are expecting non-encrypted documents here, but it is common
+ // for users to pass in a document that is encrypted with an empty
+ // password (such a document appears to not be encrypted by
+ // someone viewing the document, thus the confusion). We will
+ // attempt to decrypt with the empty password to handle this case.
+ //
+ log.debug("Document is encrypted, decrypting with empty password");
+ try
+ {
+ document.decrypt("");
+ }
+ catch (CryptographyException e)
+ {
+ throw new IOException("Error decrypting document, details: " + e.getMessage());
+ }
+ catch (InvalidPasswordException e)
+ {
+ throw new IOException("Error: document is encrypted");
+ }
+ }
+
+ processPages( document.getDocumentCatalog().getAllPages() );
+ endDocument(document);
+ }
+
+ /**
+ * This will process all of the pages and the text that is in them.
+ *
+ * @param pages The pages object in the document.
+ *
+ * @throws IOException If there is an error parsing the text.
+ */
+ protected void processPages( List pages ) throws IOException
+ {
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "processPages( " + pages + " )" );
+ }
+
+ if( startBookmark != null )
+ {
+ startBookmarkPageNumber = getPageNumber( startBookmark, pages );
+ }
+
+ if( endBookmark != null )
+ {
+ endBookmarkPageNumber = getPageNumber( endBookmark, pages );
+ }
+
+ if( startBookmarkPageNumber == -1 && startBookmark != null &&
+ endBookmarkPageNumber == -1 && endBookmark != null &&
+ startBookmark.getCOSObject() == endBookmark.getCOSObject() )
+ {
+ //this is a special case where both the start and end bookmark
+ //are the same but point to nothing. In this case
+ //we will not extract any text.
+ startBookmarkPageNumber = 0;
+ endBookmarkPageNumber = 0;
+ }
+
+
+ Iterator pageIter = pages.iterator();
+ while( pageIter.hasNext() )
+ {
+ PDPage nextPage = (PDPage)pageIter.next();
+ PDStream contentStream = nextPage.getContents();
+ if( contentStream != null )
+ {
+ COSStream contents = contentStream.getStream();
+ processPage( nextPage, contents );
+ }
+ }
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "processPages() end" );
+ }
+ }
+
+ private int getPageNumber( PDOutlineItem bookmark, List allPages ) throws IOException
+ {
+ int pageNumber = -1;
+ PDPage page = bookmark.findDestinationPage( document );
+ if( page != null )
+ {
+ pageNumber = allPages.indexOf( page )+1;//use one based indexing
+ }
+ return pageNumber;
+ }
+
+ /**
+ * This method is available for subclasses of this class. It will be called before processing
+ * of the document start.
+ *
+ * @param pdf The PDF document that is being processed.
+ * @throws IOException If an IO error occurs.
+ */
+ protected void startDocument(PDDocument pdf) throws IOException
+ {
+ // no default implementation, but available for subclasses
+ }
+
+ /**
+ * This method is available for subclasses of this class. It will be called after processing
+ * of the document finishes.
+ *
+ * @param pdf The PDF document that is being processed.
+ * @throws IOException If an IO error occurs.
+ */
+ protected void endDocument(PDDocument pdf ) throws IOException
+ {
+ // no default implementation, but available for subclasses
+ }
+
+ /**
+ * This will process the contents of a page.
+ *
+ * @param page The page to process.
+ * @param content The contents of the page.
+ *
+ * @throws IOException If there is an error processing the page.
+ */
+ protected void processPage( PDPage page, COSStream content ) throws IOException
+ {
+ long start = System.currentTimeMillis();
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "processPage( " + page + ", " + content + " )" );
+ }
+ currentPageNo++;
+ if( currentPageNo >= startPage && currentPageNo <= endPage &&
+ (startBookmarkPageNumber == -1 || currentPageNo >= startBookmarkPageNumber ) &&
+ (endBookmarkPageNumber == -1 || currentPageNo <= endBookmarkPageNumber ))
+ {
+ startPage( page );
+ pageArticles = page.getThreadBeads();
+ int numberOfArticleSections = 1 + pageArticles.size() * 2;
+ if( !shouldSeparateByBeads )
+ {
+ numberOfArticleSections = 1;
+ }
+ int originalSize = charactersByArticle.size();
+ charactersByArticle.setSize( numberOfArticleSections );
+ for( int i=0; i<numberOfArticleSections; i++ )
+ {
+ if( numberOfArticleSections < originalSize )
+ {
+ ((List)charactersByArticle.get( i )).clear();
+ }
+ else
+ {
+ charactersByArticle.set( i, new ArrayList() );
+ }
+ }
+
+ characterListMapping.clear();
+ long startProcess = System.currentTimeMillis();
+ processStream( page, page.findResources(), content );
+ long stopProcess = System.currentTimeMillis();
+ long startFlush = System.currentTimeMillis();
+ flushText();
+ long stopFlush = System.currentTimeMillis();
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "processStream time=" + (stopProcess-startProcess) );
+ log.debug( "flushText time=" + (stopFlush-startFlush) );
+ }
+ endPage( page );
+ }
+ long stop = System.currentTimeMillis();
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "processPage() end time=" + (stop-start) );
+ }
+
+ }
+
+ /**
+ * Start a new paragraph. Default implementation is to do nothing. Subclasses
+ * may provide additional information.
+ *
+ * @throws IOException If there is any error writing to the stream.
+ */
+ protected void startParagraph() throws IOException
+ {
+ //default is to do nothing.
+ }
+
+ /**
+ * End a paragraph. Default implementation is to do nothing. Subclasses
+ * may provide additional information.
+ *
+ * @throws IOException If there is any error writing to the stream.
+ */
+ protected void endParagraph() throws IOException
+ {
+ //default is to do nothing
+ }
+
+ /**
+ * Start a new page. Default implementation is to do nothing. Subclasses
+ * may provide additional information.
+ *
+ * @param page The page we are about to process.
+ *
+ * @throws IOException If there is any error writing to the stream.
+ */
+ protected void startPage( PDPage page ) throws IOException
+ {
+ //default is to do nothing.
+ }
+
+ /**
+ * End a page. Default implementation is to do nothing. Subclasses
+ * may provide additional information.
+ *
+ * @param page The page we are about to process.
+ *
+ * @throws IOException If there is any error writing to the stream.
+ */
+ protected void endPage( PDPage page ) throws IOException
+ {
+ //default is to do nothing
+ }
+
+ /**
+ * This will print the text to the output stream.
+ *
+ * @throws IOException If there is an error writing the text.
+ */
+ protected void flushText() throws IOException
+ {
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "flushText() start" );
+ }
+ float currentY = -1;
+ float lastBaselineFontSize = -1;
+ if( log.isDebugEnabled() )
+ {
+ log.debug("<Starting text object list>");
+ }
+ float endOfLastTextX = -1;
+ float startOfNextWordX = -1;
+ float lastWordSpacing = -1;
+ TextPosition lastProcessedCharacter = null;
+
+ for( int i=0; i<charactersByArticle.size(); i++)
+ {
+ startParagraph();
+ List textList = (List)charactersByArticle.get( i );
+ if( sortByPosition )
+ {
+ TextPositionComparator comparator = new TextPositionComparator( getCurrentPage() );
+ Collections.sort( textList, comparator );
+ }
+ Iterator textIter = textList.iterator();
+ while( textIter.hasNext() )
+ {
+ TextPosition position = (TextPosition)textIter.next();
+ String characterValue = position.getCharacter();
+
+ //wordSpacing = position.getWordSpacing();
+ float wordSpacing = 0;
+
+ if( wordSpacing == 0 )
+ {
+ //try to get width of a space character
+ wordSpacing = position.getWidthOfSpace();
+ //if still zero fall back to getting the width of the current
+ //character
+ if( wordSpacing == 0 )
+ {
+ wordSpacing = position.getWidth();
+ }
+ }
+
+
+ // RDD - We add a conservative approximation for space determination.
+ // basically if there is a blank area between two characters that is
+ //equal to some percentage of the word spacing then that will be the
+ //start of the next word
+ if( lastWordSpacing <= 0 )
+ {
+ startOfNextWordX = endOfLastTextX + (wordSpacing* 0.50f);
+ }
+ else
+ {
+ startOfNextWordX = endOfLastTextX + (((wordSpacing+lastWordSpacing)/2f)* 0.50f);
+ }
+
+ lastWordSpacing = wordSpacing;
+
+ // RDD - We will suppress text that is very close to the current line
+ // and which overwrites previously rendered text on this line.
+ // This is done specifically to handle a reasonably common situation
+ // where an application (MS Word, in the case of my examples) renders
+ // text four times at small (1 point) offsets in order to accomplish
+ // bold printing. You would not want to do this step if you were
+ // going to render the TextPosition objects graphically.
+ //
+ /*if ((endOfLastTextX != -1 && position.getX() < endOfLastTextX) &&
+ (currentY != -1 && Math.abs(position.getY() - currentY) < 1))
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("Suppressing text overwrite" +
+ " x: " + position.getX() +
+ " endOfLastTextX: " + endOfLastTextX +
+ " string: " + position.getCharacter());
+ }
+ continue;
+ }*/
+
+ // RDD - Here we determine whether this text object is on the current
+ // line. We use the lastBaselineFontSize to handle the superscript
+ // case, and the size of the current font to handle the subscript case.
+ // Text must overlap with the last rendered baseline text by at least
+ // a small amount in order to be considered as being on the same line.
+ //
+ int verticalScaling = 1;
+ if( lastBaselineFontSize < 0 || position.getFontSize() < 0 )
+ {
+ verticalScaling = -1;
+ }
+ if (currentY != -1 &&
+ ((position.getY() < (currentY - (lastBaselineFontSize * 0.9f * verticalScaling))) ||
+ (position.getY() > (currentY + (position.getFontSize() * 0.9f * verticalScaling)))))
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("<newline currentY=" + currentY + ", y=" + position.getY() +
+ " fs=" + position.getFontSize()+ " lb fs=" + lastBaselineFontSize + ">");
+ }
+ output.write(lineSeparator);
+ endOfLastTextX = -1;
+ startOfNextWordX = -1;
+ currentY = -1;
+ lastBaselineFontSize = -1;
+ }
+
+ if (startOfNextWordX != -1 && startOfNextWordX < position.getX() &&
+ lastProcessedCharacter != null &&
+ //only bother adding a space if the last character was not a space
+ lastProcessedCharacter.getCharacter() != null &&
+ !lastProcessedCharacter.getCharacter().endsWith( " " ) )
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("<space startOfNextWordX=" + startOfNextWordX + ", x=" + position.getX() + ">");
+ }
+ output.write( wordSeparator );
+ }
+
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("flushText" +
+ " x=" + position.getX() +
+ " y=" + position.getY() +
+ " xScale=" + position.getXScale() +
+ " yScale=" + position.getYScale() +
+ " width=" + position.getWidth() +
+ " currentY=" + currentY +
+ " endOfLastTextX=" + endOfLastTextX +
+ " startOfNextWordX=" + startOfNextWordX +
+ " fontSize=" + position.getFontSize() +
+ " wordSpacing=" + wordSpacing +
+ " string=\"" + characterValue + "\"");
+ }
+
+ if (currentY == -1)
+ {
+ currentY = position.getY();
+ }
+
+ if (currentY == position.getY())
+ {
+ lastBaselineFontSize = position.getFontSize();
+ }
+
+ // RDD - endX is what PDF considers to be the x coordinate of the
+ // end position of the text. We use it in computing our metrics below.
+ //
+ endOfLastTextX = position.getX() + position.getWidth();
+
+
+ if (characterValue != null)
+ {
+ output.write(characterValue);
+ }
+ else
+ {
+ log.debug( "Position.getString() is null so not writing anything" );
+ }
+ lastProcessedCharacter = position;
+ }
+ endParagraph();
+ }
+
+
+ // RDD - newline at end of flush - required for end of page (so that the top
+ // of the next page starts on its own line.
+ //
+ if( log.isDebugEnabled() )
+ {
+ log.debug("<newline endOfFlush=\"true\">");
+ }
+ output.write(pageSeparator);
+
+ output.flush();
+ }
+
+ /**
+ * Write the string to the output stream.
+ *
+ * @param text The text to write to the stream.
+ * @throws IOException If there is an error when writing the text.
+ */
+ protected void writeCharacters( TextPosition text ) throws IOException
+ {
+ output.write( text.getCharacter() );
+ }
+
+ /**
+ * This will determine of two floating point numbers are within a specified variance.
+ *
+ * @param first The first number to compare to.
+ * @param second The second number to compare to.
+ * @param variance The allowed variance.
+ */
+ private boolean within( float first, float second, float variance )
+ {
+ return second > first - variance && second < first + variance;
+ }
+
+ /**
+ * This will show add a character to the list of characters to be printed to
+ * the text file.
+ *
+ * @param text The description of the character to display.
+ */
+ protected void showCharacter( TextPosition text )
+ {
+ boolean showCharacter = true;
+ if( suppressDuplicateOverlappingText )
+ {
+ showCharacter = false;
+ String textCharacter = text.getCharacter();
+ float textX = text.getX();
+ float textY = text.getY();
+ List sameTextCharacters = (List)characterListMapping.get( textCharacter );
+ if( sameTextCharacters == null )
+ {
+ sameTextCharacters = new ArrayList();
+ characterListMapping.put( textCharacter, sameTextCharacters );
+ }
+
+ // RDD - Here we compute the value that represents the end of the rendered
+ // text. This value is used to determine whether subsequent text rendered
+ // on the same line overwrites the current text.
+ //
+ // We subtract any positive padding to handle cases where extreme amounts
+ // of padding are applied, then backed off (not sure why this is done, but there
+ // are cases where the padding is on the order of 10x the character width, and
+ // the TJ just backs up to compensate after each character). Also, we subtract
+ // an amount to allow for kerning (a percentage of the width of the last
+ // character).
+ //
+ boolean suppressCharacter = false;
+ float tolerance = (text.getWidth()/textCharacter.length())/3.0f;
+ for( int i=0; i<sameTextCharacters.size() && textCharacter != null; i++ )
+ {
+ TextPosition character = (TextPosition)sameTextCharacters.get( i );
+ String charCharacter = character.getCharacter();
+ float charX = character.getX();
+ float charY = character.getY();
+ //only want to suppress
+
+ if( charCharacter != null &&
+ //charCharacter.equals( textCharacter ) &&
+ within( charX, textX, tolerance ) &&
+ within( charY,
+ textY,
+ tolerance ) )
+ {
+ if( log.isDebugEnabled() )
+ {
+ log.debug("suppressText" +
+ " x=" + charX +
+ " y=" + charY +
+ " width=" + character.getWidth() +
+ " fontSize=" + character.getFontSize() +
+ " string=\"" + charCharacter + "\"");
+ }
+ suppressCharacter = true;
+ }
+ }
+ if( !suppressCharacter )
+ {
+ sameTextCharacters.add( text );
+ showCharacter = true;
+ }
+ }
+
+ if( showCharacter )
+ {
+ //if we are showing the character then we need to determine which
+ //article it belongs to.
+ int foundArticleDivisionIndex = -1;
+ int notFoundButFirstLeftAndAboveArticleDivisionIndex = -1;
+ int notFoundButFirstLeftArticleDivisionIndex = -1;
+ int notFoundButFirstAboveArticleDivisionIndex = -1;
+ float x = text.getX();
+ float y = text.getY();
+ if( shouldSeparateByBeads )
+ {
+ for( int i=0; i<pageArticles.size() && foundArticleDivisionIndex == -1; i++ )
+ {
+ PDThreadBead bead = (PDThreadBead)pageArticles.get( i );
+ if( bead != null )
+ {
+ PDRectangle rect = bead.getRectangle();
+ if( rect.contains( x, y ) )
+ {
+ foundArticleDivisionIndex = i*2+1;
+ }
+ else if( (x < rect.getLowerLeftX() ||
+ y < rect.getUpperRightY()) &&
+ notFoundButFirstLeftAndAboveArticleDivisionIndex == -1)
+ {
+ notFoundButFirstLeftAndAboveArticleDivisionIndex = i*2;
+ }
+ else if( x < rect.getLowerLeftX() &&
+ notFoundButFirstLeftArticleDivisionIndex == -1)
+ {
+ notFoundButFirstLeftArticleDivisionIndex = i*2;
+ }
+ else if( y < rect.getUpperRightY() &&
+ notFoundButFirstAboveArticleDivisionIndex == -1)
+ {
+ notFoundButFirstAboveArticleDivisionIndex = i*2;
+ }
+ }
+ else
+ {
+ foundArticleDivisionIndex = 0;
+ }
+ }
+ }
+ else
+ {
+ foundArticleDivisionIndex = 0;
+ }
+ int articleDivisionIndex = -1;
+ if( foundArticleDivisionIndex != -1 )
+ {
+ articleDivisionIndex = foundArticleDivisionIndex;
+ }
+ else if( notFoundButFirstLeftAndAboveArticleDivisionIndex != -1 )
+ {
+ articleDivisionIndex = notFoundButFirstLeftAndAboveArticleDivisionIndex;
+ }
+ else if( notFoundButFirstLeftArticleDivisionIndex != -1 )
+ {
+ articleDivisionIndex = notFoundButFirstLeftArticleDivisionIndex;
+ }
+ else if( notFoundButFirstAboveArticleDivisionIndex != -1 )
+ {
+ articleDivisionIndex = notFoundButFirstAboveArticleDivisionIndex;
+ }
+ else
+ {
+ articleDivisionIndex = charactersByArticle.size()-1;
+ }
+ List textList = (List) charactersByArticle.get( articleDivisionIndex );
+ textList.add( text );
+ }
+ }
+
+ /**
+ * This is the page that the text extraction will start on. The pages start
+ * at page 1. For example in a 5 page PDF document, if the start page is 1
+ * then all pages will be extracted. If the start page is 4 then pages 4 and 5
+ * will be extracted. The default value is 1.
+ *
+ * @return Value of property startPage.
+ */
+ public int getStartPage()
+ {
+ return startPage;
+ }
+
+ /**
+ * This will set the first page to be extracted by this class.
+ *
+ * @param startPageValue New value of property startPage.
+ */
+ public void setStartPage(int startPageValue)
+ {
+ startPage = startPageValue;
+ }
+
+ /**
+ * This will get the last page that will be extracted. This is inclusive,
+ * for example if a 5 page PDF an endPage value of 5 would extract the
+ * entire document, an end page of 2 would extract pages 1 and 2. This defaults
+ * to Integer.MAX_VALUE such that all pages of the pdf will be extracted.
+ *
+ * @return Value of property endPage.
+ */
+ public int getEndPage()
+ {
+ return endPage;
+ }
+
+ /**
+ * This will set the last page to be extracted by this class.
+ *
+ * @param endPageValue New value of property endPage.
+ */
+ public void setEndPage(int endPageValue)
+ {
+ endPage = endPageValue;
+ }
+
+ /**
+ * Set the desired line separator for output text. The line.separator
+ * system property is used if the line separator preference is not set
+ * explicitly using this method.
+ *
+ * @param separator The desired line separator string.
+ */
+ public void setLineSeparator(String separator)
+ {
+ lineSeparator = separator;
+ }
+
+ /**
+ * This will get the line separator.
+ *
+ * @return The desired line separator string.
+ */
+ public String getLineSeparator()
+ {
+ return lineSeparator;
+ }
+
+ /**
+ * Set the desired page separator for output text. The line.separator
+ * system property is used if the page separator preference is not set
+ * explicitly using this method.
+ *
+ * @param separator The desired page separator string.
+ */
+ public void setPageSeparator(String separator)
+ {
+ pageSeparator = separator;
+ }
+
+ /**
+ * This will get the word separator.
+ *
+ * @return The desired word separator string.
+ */
+ public String getWordSeparator()
+ {
+ return wordSeparator;
+ }
+
+ /**
+ * Set the desired word separator for output text. The PDFBox text extraction
+ * algorithm will output a space character if there is enough space between
+ * two words. By default a space character is used. If you need and accurate
+ * count of characters that are found in a PDF document then you might want to
+ * set the word separator to the empty string.
+ *
+ * @param separator The desired page separator string.
+ */
+ public void setWordSeparator(String separator)
+ {
+ wordSeparator = separator;
+ }
+
+ /**
+ * This will get the page separator.
+ *
+ * @return The page separator string.
+ */
+ public String getPageSeparator()
+ {
+ return pageSeparator;
+ }
+ /**
+ * @return Returns the suppressDuplicateOverlappingText.
+ */
+ public boolean shouldSuppressDuplicateOverlappingText()
+ {
+ return suppressDuplicateOverlappingText;
+ }
+
+ /**
+ * Get the current page number that is being processed.
+ *
+ * @return A 1 based number representing the current page.
+ */
+ protected int getCurrentPageNo()
+ {
+ return currentPageNo;
+ }
+
+ /**
+ * The output stream that is being written to.
+ *
+ * @return The stream that output is being written to.
+ */
+ protected Writer getOutput()
+ {
+ return output;
+ }
+
+ /**
+ * Character strings are grouped by articles. It is quite common that there
+ * will only be a single article. This returns a List that contains List objects,
+ * the inner lists will contain TextPosition objects.
+ *
+ * @return A double List of TextPositions for all text strings on the page.
+ */
+ protected List getCharactersByArticle()
+ {
+ return charactersByArticle;
+ }
+
+ /**
+ * By default the text stripper will attempt to remove text that overlapps each other.
+ * Word paints the same character several times in order to make it look bold. By setting
+ * this to false all text will be extracted, which means that certain sections will be
+ * duplicated, but better performance will be noticed.
+ *
+ * @param suppressDuplicateOverlappingTextValue The suppressDuplicateOverlappingText to set.
+ */
+ public void setSuppressDuplicateOverlappingText(
+ boolean suppressDuplicateOverlappingTextValue)
+ {
+ this.suppressDuplicateOverlappingText = suppressDuplicateOverlappingTextValue;
+ }
+
+ /**
+ * This will tell if the text stripper should separate by beads.
+ *
+ * @return If the text will be grouped by beads.
+ */
+ public boolean shouldSeparateByBeads()
+ {
+ return shouldSeparateByBeads;
+ }
+
+ /**
+ * Set if the text stripper should group the text output by a list of beads. The default value is true!
+ *
+ * @param aShouldSeparateByBeads The new grouping of beads.
+ */
+ public void setShouldSeparateByBeads(boolean aShouldSeparateByBeads)
+ {
+ this.shouldSeparateByBeads = aShouldSeparateByBeads;
+ }
+
+ /**
+ * Get the bookmark where text extraction should end, inclusive. Default is null.
+ *
+ * @return The ending bookmark.
+ */
+ public PDOutlineItem getEndBookmark()
+ {
+ return endBookmark;
+ }
+
+ /**
+ * Set the bookmark where the text extraction should stop.
+ *
+ * @param aEndBookmark The ending bookmark.
+ */
+ public void setEndBookmark(PDOutlineItem aEndBookmark)
+ {
+ endBookmark = aEndBookmark;
+ }
+
+ /**
+ * Get the bookmark where text extraction should start, inclusive. Default is null.
+ *
+ * @return The starting bookmark.
+ */
+ public PDOutlineItem getStartBookmark()
+ {
+ return startBookmark;
+ }
+
+ /**
+ * Set the bookmark where text extraction should start, inclusive.
+ *
+ * @param aStartBookmark The starting bookmark.
+ */
+ public void setStartBookmark(PDOutlineItem aStartBookmark)
+ {
+ startBookmark = aStartBookmark;
+ }
+
+ /**
+ * This will tell if the text stripper should sort the text tokens
+ * before writing to the stream.
+ *
+ * @return true If the text tokens will be sorted before being written.
+ */
+ public boolean shouldSortByPosition()
+ {
+ return sortByPosition;
+ }
+
+ /**
+ * The order of the text tokens in a PDF file may not be in the same
+ * as they appear visually on the screen. For example, a PDF writer may
+ * write out all text by font, so all bold or larger text, then make a second
+ * pass and write out the normal text.<br/>
+ * The default is to <b>not</b> sort by position.<br/>
+ * <br/>
+ * A PDF writer could choose to write each character in a different order. By
+ * default PDFBox does <b>not</b> sort the text tokens before processing them due to
+ * performance reasons.
+ *
+ * @param newSortByPosition Tell PDFBox to sort the text positions.
+ */
+ public void setSortByPosition(boolean newSortByPosition)
+ {
+ sortByPosition = newSortByPosition;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/PDFTextStripperByArea.java b/src/main/java/org/pdfbox/util/PDFTextStripperByArea.java
new file mode 100644
index 0000000..91c76a5
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/PDFTextStripperByArea.java
@@ -0,0 +1,165 @@
+/**
+ * Copyright (c) 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.util;
+
+import java.awt.Rectangle;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.pdfbox.cos.COSStream;
+import org.pdfbox.pdmodel.PDPage;
+import org.pdfbox.pdmodel.common.PDStream;
+
+/**
+ * This will extract text from a specified region in the PDF.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.3 $
+ */
+public class PDFTextStripperByArea extends PDFTextStripper
+{
+ private List regions = new ArrayList();
+ private Map regionArea = new HashMap();
+ private Map regionCharacterList = new HashMap();
+ private Map regionText = new HashMap();
+
+ /**
+ * Constructor.
+ * @throws IOException If there is an error loading properties.
+ */
+ public PDFTextStripperByArea() throws IOException
+ {
+ super();
+ }
+
+ /**
+ * Add a new region to group text by.
+ *
+ * @param regionName The name of the region.
+ * @param rect The rectangle area to retrieve the text from.
+ */
+ public void addRegion( String regionName, Rectangle rect )
+ {
+ regions.add( regionName );
+ regionArea.put( regionName, rect );
+ }
+
+ /**
+ * Get the list of regions that have been setup.
+ *
+ * @return A list of java.lang.String objects to identify the region names.
+ */
+ public List getRegions()
+ {
+ return regions;
+ }
+
+ /**
+ * Get the text for the region, this should be called after extractRegions().
+ *
+ * @param regionName The name of the region to get the text from.
+ * @return The text that was identified in that region.
+ */
+ public String getTextForRegion( String regionName )
+ {
+ StringWriter text = (StringWriter)regionText.get( regionName );
+ return text.toString();
+ }
+
+ /**
+ * Process the page to extract the region text.
+ *
+ * @param page The page to extract the regions from.
+ * @throws IOException If there is an error while extracting text.
+ */
+ public void extractRegions( PDPage page ) throws IOException
+ {
+ Iterator regionIter = regions.iterator();
+ while( regionIter.hasNext() )
+ {
+ //reset the stored text for the region so this class
+ //can be reused.
+ String regionName = (String)regionIter.next();
+ Vector regionCharactersByArticle = new Vector();
+ regionCharactersByArticle.add( new ArrayList() );
+ regionCharacterList.put( regionName, regionCharactersByArticle );
+ regionText.put( regionName, new StringWriter() );
+ }
+
+ PDStream contentStream = page.getContents();
+ if( contentStream != null )
+ {
+ COSStream contents = contentStream.getStream();
+ processPage( page, contents );
+ }
+ }
+
+ /**
+ * @see PDFTextStripper#showCharacter(TextPosition)
+ */
+ protected void showCharacter( TextPosition text )
+ {
+ Iterator regionIter = regionArea.keySet().iterator();
+ while( regionIter.hasNext() )
+ {
+ String region = (String)regionIter.next();
+ Rectangle rect = (Rectangle)regionArea.get( region );
+ if( rect.contains( text.getX(), text.getY() ) )
+ {
+ charactersByArticle = (Vector)regionCharacterList.get( region );
+ super.showCharacter( text );
+ }
+ }
+ }
+
+ /**
+ * This will print the text to the output stream.
+ *
+ * @throws IOException If there is an error writing the text.
+ */
+ protected void flushText() throws IOException
+ {
+ Iterator regionIter = regionArea.keySet().iterator();
+ while( regionIter.hasNext() )
+ {
+ String region = (String)regionIter.next();
+ charactersByArticle = (Vector)regionCharacterList.get( region );
+ output = (StringWriter)regionText.get( region );
+ super.flushText();
+ }
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/ResourceLoader.java b/src/main/java/org/pdfbox/util/ResourceLoader.java
new file mode 100644
index 0000000..0f80d09
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/ResourceLoader.java
@@ -0,0 +1,169 @@
+/**
+ * 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.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import java.util.Properties;
+
+import org.apache.log4j.Logger;
+
+/**
+ * This class will handle loading resource files(AFM/CMAP).
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.6 $
+ */
+public class ResourceLoader
+{
+ private static Logger log = Logger.getLogger( ResourceLoader.class );
+
+ /**
+ * private constructor for utility class.
+ */
+ private ResourceLoader()
+ {
+ //private utility class
+ }
+
+ /**
+ * This will attempt to load the resource given the resource name.
+ *
+ * @param resourceName The resource to try and load.
+ *
+ * @return The resource as a stream or null if it could not be found.
+ *
+ * @throws IOException If there is an error while attempting to load the resource.
+ */
+ public static InputStream loadResource( String resourceName ) throws IOException
+ {
+ if( log.isDebugEnabled() )
+ {
+ log.debug( "loadResource( " + resourceName + ")" );
+ }
+
+ ClassLoader loader = ResourceLoader.class.getClassLoader();
+
+ InputStream is = null;
+
+ if( loader != null )
+ {
+ is = loader.getResourceAsStream( resourceName );
+ }
+
+ //see sourceforge bug 863053, this is a fix for a user that
+ //needed to have PDFBox loaded by the bootstrap classloader
+ if( is == null )
+ {
+ loader = ClassLoader.getSystemClassLoader();
+ if( loader != null )
+ {
+ is = loader.getResourceAsStream( resourceName );
+ }
+ }
+
+ if( is == null )
+ {
+ File f = new File( resourceName );
+ if( f.exists() )
+ {
+ is = new FileInputStream( f );
+ }
+ }
+
+ return is;
+ }
+
+ /**
+ * This will attempt to load the resource given the resource name.
+ *
+ * @param resourceName The resource to try and load.
+ *
+ * @return The resource as a stream or null if it could not be found.
+ *
+ * @throws IOException If there is an error loading the properties.
+ */
+ public static Properties loadProperties( String resourceName ) throws IOException
+ {
+ Properties properties = null;
+ InputStream is = null;
+ try
+ {
+ is = loadResource( resourceName );
+ if( is != null )
+ {
+ properties = new Properties();
+ properties.load( is );
+ }
+ }
+ finally
+ {
+ if( is != null )
+ {
+ is.close();
+ }
+ }
+ return properties;
+ }
+
+ /**
+ * This will attempt to load the resource given the resource name.
+ *
+ * @param resourceName The resource to try and load.
+ * @param defaults A stream of default properties.
+ *
+ * @return The resource as a stream or null if it could not be found.
+ *
+ * @throws IOException If there is an error loading the properties.
+ */
+ public static Properties loadProperties( String resourceName, Properties defaults ) throws IOException
+ {
+ InputStream is = null;
+ try
+ {
+ is = loadResource( resourceName );
+ if( is != null )
+ {
+ defaults.load( is );
+ }
+ }
+ finally
+ {
+ if( is != null )
+ {
+ is.close();
+ }
+ }
+ return defaults;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/SimpleConfigurator.java b/src/main/java/org/pdfbox/util/SimpleConfigurator.java
new file mode 100644
index 0000000..df94029
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/SimpleConfigurator.java
@@ -0,0 +1,68 @@
+/**
+ * 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.util;
+
+import java.net.URL;
+
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.Logger;
+import org.apache.log4j.Level;
+
+import org.apache.log4j.spi.Configurator;
+import org.apache.log4j.spi.LoggerRepository;
+
+/**
+ * Log4J configurator.
+ *
+ * @author Robert Dickinson (bob@brutesquadlabs.com)
+ * @version $Revision: 1.2 $
+ */
+public class SimpleConfigurator implements Configurator
+{
+ /**
+ * Constructor.
+ */
+ public SimpleConfigurator()
+ {
+ }
+
+ /**
+ * Interpret a resource pointed to by a URL and set up log4J accordingly.
+ * The configuration is done relative to the <code>heirarchy</code> parameter.
+ *
+ * @param url The URL to parse
+ * @param repository The heirarchy to operate upon
+ */
+ public void doConfigure(URL url, LoggerRepository repository)
+ {
+ BasicConfigurator.configure();
+ Logger.getRootLogger().setLevel(Level.DEBUG);
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/Splitter.java b/src/main/java/org/pdfbox/util/Splitter.java
new file mode 100644
index 0000000..c03a989
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/Splitter.java
@@ -0,0 +1,201 @@
+/**
+ * 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.util;
+
+import org.pdfbox.pdmodel.PDDocument;
+import org.pdfbox.pdmodel.PDPage;
+
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Split a document into several other documents.
+ *
+ * @author Mario Ivankovits (mario@ops.co.at)
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.6 $
+ */
+public class Splitter
+{
+
+ /**
+ * The source PDF document.
+ */
+ protected PDDocument pdfDocument;
+
+ /**
+ * The current PDF document that contains the splitted page.
+ */
+ protected PDDocument currentDocument = null;
+
+ private int splitAtPage=1;
+ private List newDocuments = null;
+
+ /**
+ * The current page number that we are processing, zero based.
+ */
+ protected int pageNumber = 0;
+
+ /**
+ * This will take a document and split into several other documents.
+ *
+ * @param document The document to split.
+ *
+ * @return A list of all the split documents.
+ *
+ * @throws IOException If there is an IOError
+ */
+ public List split( PDDocument document ) throws IOException
+ {
+ newDocuments = new ArrayList();
+ pdfDocument = document;
+
+ List pages = pdfDocument.getDocumentCatalog().getAllPages();
+ processPages(pages);
+ return newDocuments;
+ }
+
+ /**
+ * This will tell the splitting algorithm where to split the pages. The default
+ * is 1, so every page will become a new document. If it was to then each document would
+ * contain 2 pages. So it the source document had 5 pages it would split into
+ * 3 new documents, 2 documents containing 2 pages and 1 document containing one
+ * page.
+ *
+ * @param split The number of pages each split document should contain.
+ */
+ public void setSplitAtPage( int split )
+ {
+ if( split <= 0 )
+ {
+ throw new RuntimeException( "Error split must be at least one page." );
+ }
+ splitAtPage = split;
+ }
+
+ /**
+ * This will return how many pages each split document will contain.
+ *
+ * @return The split parameter.
+ */
+ public int getSplitAtPage()
+ {
+ return splitAtPage;
+ }
+
+ /**
+ * Interface method to handle the start of the page processing.
+ *
+ * @param pages The list of pages from the source document.
+ *
+ * @throws IOException If an IO error occurs.
+ */
+ protected void processPages(List pages) throws IOException
+ {
+ Iterator iter = pages.iterator();
+ while( iter.hasNext() )
+ {
+ PDPage page = (PDPage)iter.next();
+ processNextPage( page );
+ }
+ }
+
+ /**
+ * Interface method, you can control where a document gets split by implementing
+ * this method. By default a split occurs at every page. If you wanted to split
+ * based on some complex logic then you could override this method. For example.
+ * <code>
+ * protected void createNewDocumentIfNecessary()
+ * {
+ * if( isPrime( pageNumber ) )
+ * {
+ * super.createNewDocumentIfNecessary();
+ * }
+ * }
+ * </code>
+ *
+ * @throws IOException If there is an error creating the new document.
+ */
+ protected void createNewDocumentIfNecessary() throws IOException
+ {
+ if (isNewDocNecessary())
+ {
+ createNewDocument();
+ }
+ }
+
+ /**
+ * Check if it is necessary to create a new document.
+ *
+ * @return true If a new document should be created.
+ */
+ protected boolean isNewDocNecessary()
+ {
+ return pageNumber % splitAtPage == 0 || currentDocument == null;
+ }
+
+ /**
+ * Create a new document to write the splitted contents to.
+ *
+ * @throws IOException If there is an problem creating the new document.
+ */
+ protected void createNewDocument() throws IOException
+ {
+ currentDocument = new PDDocument();
+ currentDocument.setDocumentInformation(pdfDocument.getDocumentInformation());
+ currentDocument.getDocumentCatalog().setViewerPreferences(
+ pdfDocument.getDocumentCatalog().getViewerPreferences());
+ newDocuments.add(currentDocument);
+ }
+
+
+
+ /**
+ * Interface to start processing a new page.
+ *
+ * @param page The page that is about to get processed.
+ *
+ * @throws IOException If there is an error creating the new document.
+ */
+ protected void processNextPage( PDPage page ) throws IOException
+ {
+ createNewDocumentIfNecessary();
+ PDPage imported = currentDocument.importPage( page );
+ imported.setCropBox( page.findCropBox() );
+ imported.setMediaBox( page.findMediaBox() );
+ imported.setResources( page.findResources() );
+ imported.setRotation( page.findRotation() );
+ pageNumber++;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/TextPosition.java b/src/main/java/org/pdfbox/util/TextPosition.java
new file mode 100644
index 0000000..f44ca56
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/TextPosition.java
@@ -0,0 +1,203 @@
+/**
+ * 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.util;
+
+import org.pdfbox.pdmodel.font.PDFont;
+
+/**
+ * This represents a character and a position on the screen of those characters.
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.9 $
+ */
+public class TextPosition
+{
+ private float x;
+ private float y;
+ private float xScale;
+ private float yScale;
+ private float width;
+ private float widthOfSpace;
+ private String c;
+ private PDFont font;
+ private float fontSize;
+ private float wordSpacing;
+
+ /**
+ * Constructor.
+ *
+ * @param xPos The x coordinate of the character.
+ * @param yPos The y coordinate of the character.
+ * @param xScl The x scaling of the character.
+ * @param yScl The y scaling of the character.
+ * @param widthValue The width of the character.
+ * @param spaceWidth The width of the space character.
+ * @param string The character to be displayed.
+ * @param currentFont The current for for this text position.
+ * @param fontSizeValue The new font size.
+ * @param ws The word spacing parameter
+ */
+ public TextPosition(
+ float xPos,
+ float yPos,
+ float xScl,
+ float yScl,
+ float widthValue,
+ float spaceWidth,
+ String string,
+ PDFont currentFont,
+ float fontSizeValue,
+ float ws
+ )
+ {
+ this.x = xPos;
+ this.y = yPos;
+ this.xScale = xScl;
+ this.yScale = yScl;
+ this.width = widthValue;
+ this.widthOfSpace = spaceWidth;
+ this.c = string;
+ this.font = currentFont;
+ this.fontSize = fontSizeValue;
+ this.wordSpacing = ws;
+ }
+
+ /**
+ * This will the character that will be displayed on the screen.
+ *
+ * @return The character on the screen.
+ */
+ public String getCharacter()
+ {
+ return c;
+ }
+
+ /**
+ * This will get the x position of the character.
+ *
+ * @return The x coordinate of the character.
+ */
+ public float getX()
+ {
+ return x;
+ }
+
+ /**
+ * This will get the y position of the character.
+ *
+ * @return The y coordinate of the character.
+ */
+ public float getY()
+ {
+ return y;
+ }
+
+ /**
+ * This will get with width of this character.
+ *
+ * @return The width of this character.
+ */
+ public float getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * This will get the font size that this object is
+ * suppose to be drawn at.
+ *
+ * @return The font size.
+ */
+ public float getFontSize()
+ {
+ return fontSize;
+ }
+
+ /**
+ * This will get the font for the text being drawn.
+ *
+ * @return The font size.
+ */
+ public PDFont getFont()
+ {
+ return font;
+ }
+
+ /**
+ * This will get the current word spacing.
+ *
+ * @return The current word spacing.
+ */
+ public float getWordSpacing()
+ {
+ return wordSpacing;
+ }
+
+ /**
+ * This will get the width of a space character. This is useful for some
+ * algorithms such as the text stripper, that need to know the width of a
+ * space character.
+ *
+ * @return The width of a space character.
+ */
+ public float getWidthOfSpace()
+ {
+ return widthOfSpace;
+ }
+ /**
+ * @return Returns the xScale.
+ */
+ public float getXScale()
+ {
+ return xScale;
+ }
+ /**
+ * @param scale The xScale to set.
+ */
+ public void setXScale(float scale)
+ {
+ xScale = scale;
+ }
+ /**
+ * @return Returns the yScale.
+ */
+ public float getYScale()
+ {
+ return yScale;
+ }
+ /**
+ * @param scale The yScale to set.
+ */
+ public void setYScale(float scale)
+ {
+ yScale = scale;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/TextPositionComparator.java b/src/main/java/org/pdfbox/util/TextPositionComparator.java
new file mode 100644
index 0000000..fab6a6e
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/TextPositionComparator.java
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 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.util;
+
+import java.util.Comparator;
+
+import org.pdfbox.pdmodel.PDPage;
+
+/**
+ * This class is a comparator for TextPosition operators.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.2 $
+ */
+public class TextPositionComparator implements Comparator
+{
+ private PDPage thePage = null;
+
+ /**
+ * Constuctor, comparison of TextPosition depends on the rotation
+ * of the page.
+ * @param page The page that the text position is on.
+ */
+ public TextPositionComparator( PDPage page )
+ {
+ thePage = page;
+ }
+
+ /**
+ * @see Comparator#compare(java.lang.Object, java.lang.Object)
+ */
+ public int compare(Object o1, Object o2)
+ {
+ int retval = 0;
+ TextPosition pos1 = (TextPosition)o1;
+ TextPosition pos2 = (TextPosition)o2;
+ int rotation = thePage.findRotation();
+ float x1 = 0;
+ float x2 = 0;
+ float y1 = 0;
+ float y2 = 0;
+ if( rotation == 0 )
+ {
+ x1 = pos1.getX();
+ x2 = pos2.getX();
+ y1 = pos1.getY();
+ y2 = pos2.getY();
+ }
+ else if( rotation == 90 )
+ {
+ x1 = pos1.getY();
+ x2 = pos2.getX();
+ y1 = pos1.getX();
+ y2 = pos2.getY();
+ }
+ else if( rotation == 180 )
+ {
+ x1 = -pos1.getX();
+ x2 = -pos2.getX();
+ y1 = -pos1.getY();
+ y2 = -pos2.getY();
+ }
+ else if( rotation == 270 )
+ {
+ x1 = -pos1.getY();
+ x2 = -pos2.getY();
+ y1 = -pos1.getX();
+ y2 = -pos2.getX();
+ }
+
+ if( y1 < y2 )
+ {
+ retval = -1;
+ }
+ else if( y1 > y2 )
+ {
+ return 1;
+ }
+ else
+ {
+ if( x1 < x2 )
+ {
+ retval = -1;
+ }
+ else if( x1 > x2 )
+ {
+ retval = 1;
+ }
+ else
+ {
+ retval = 0;
+ }
+ }
+
+ return retval;
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/org/pdfbox/util/XMLUtil.java b/src/main/java/org/pdfbox/util/XMLUtil.java
new file mode 100644
index 0000000..1798aa2
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/XMLUtil.java
@@ -0,0 +1,103 @@
+/**
+ * Copyright (c) 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.util;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+/**
+ * This class with handle some simple XML operations.
+ *
+ * @author blitchfield
+ * @version $Revision: 1.2 $
+ */
+public class XMLUtil
+{
+ /**
+ * Utility class, should not be instantiated.
+ *
+ */
+ private XMLUtil()
+ {
+ }
+
+ /**
+ * This will parse an XML stream and create a DOM document.
+ *
+ * @param is The stream to get the XML from.
+ * @return The DOM document.
+ * @throws IOException It there is an error creating the dom.
+ */
+ public static Document parse( InputStream is ) throws IOException
+ {
+ try
+ {
+ DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = builderFactory.newDocumentBuilder();
+ return builder.parse( is );
+ }
+ catch( Exception e )
+ {
+ IOException thrown = new IOException( e.getMessage() );
+ throw thrown;
+ }
+ }
+
+ /**
+ * This will get the text value of an element.
+ *
+ * @param node The node to get the text value for.
+ * @return The text of the node.
+ */
+ public static String getNodeValue( Element node )
+ {
+ String retval = "";
+ NodeList children = node.getChildNodes();
+ for( int i=0; i<children.getLength(); i++ )
+ {
+ Node next = children.item( i );
+ if( next instanceof Text )
+ {
+ retval = next.getNodeValue();
+ }
+ }
+ return retval;
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/BeginText.java b/src/main/java/org/pdfbox/util/operator/BeginText.java
new file mode 100644
index 0000000..2b6af60
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/BeginText.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.util.Matrix;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ *
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class :
+* the long sequence of conditions in processOperator is remplaced
+* by this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.3 $
+ */
+public class BeginText extends OperatorProcessor
+{
+
+ private static final Logger LOG = Logger.getLogger(BeginText.class);
+
+ /**
+ * process : BT : Begin text object.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ if( LOG.isDebugEnabled() )
+ {
+ LOG.debug("<BT> " + this.toString()+ " from " + context.toString());
+ }
+ context.setTextMatrix( new Matrix());
+ context.setTextLineMatrix( new Matrix() );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/Concatenate.java b/src/main/java/org/pdfbox/util/operator/Concatenate.java
new file mode 100644
index 0000000..7fc986c
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/Concatenate.java
@@ -0,0 +1,106 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.pdfbox.cos.COSNumber;
+import org.apache.log4j.Logger;
+import org.pdfbox.util.Matrix;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ *
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class :
+* the long sequence of conditions in processOperator is remplaced by
+* this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.3 $
+ */
+
+public class Concatenate extends OperatorProcessor
+{
+
+ private static final Logger LOG = Logger.getLogger(Concatenate.class);
+
+ /**
+ * process : cm : Concatenate matrix to current transformation matrix.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+
+ //concatenate matrix to current transformation 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("<cm " +
+ "a=\"" + a.floatValue() + "\" " +
+ "b=\"" + b.floatValue() + "\" " +
+ "c=\"" + c.floatValue() + "\" " +
+ "d=\"" + d.floatValue() + "\" " +
+ "e=\"" + e.floatValue() + "\" " +
+ "f=\"" + f.floatValue() + "\" > " +
+ this.toString() + " from " + context.toString());
+ }
+
+ Matrix newMatrix = new Matrix();
+ newMatrix.setValue(0, 0, a.floatValue());
+ newMatrix.setValue(0, 1, b.floatValue());
+ newMatrix.setValue(1, 0, c.floatValue());
+ newMatrix.setValue(1, 1, d.floatValue());
+ newMatrix.setValue(2, 0, e.floatValue());
+ newMatrix.setValue(2, 1, f.floatValue());
+
+ // wprinz: BUG Fix:
+ // In PDF, matrices have to be multiplied from left to right
+ // (the new matrix is left, the old one(s) are right)
+
+ Matrix old_ctm = context.getGraphicsState().getCurrentTransformationMatrix();
+ Matrix matrix_to_concat = newMatrix;
+ Matrix new_ctm = matrix_to_concat.multiply(old_ctm);
+ context.getGraphicsState().setCurrentTransformationMatrix(
+ new_ctm );
+
+ // :wprinz
+
+ }
+
+}
diff --git a/src/main/java/org/pdfbox/util/operator/EndText.java b/src/main/java/org/pdfbox/util/operator/EndText.java
new file mode 100644
index 0000000..2794ccf
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/EndText.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.util.PDFOperator;
+/**
+ *
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class : the
+* long sequence of conditions in processOperator is remplaced by
+* this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.3 $
+ */
+public class EndText extends OperatorProcessor
+{
+
+ private static final Logger LOG = Logger.getLogger(EndText.class);
+
+ /**
+ * process : ET : End text object.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ if( LOG.isDebugEnabled() )
+ {
+ LOG.debug("<ET> "+ this.toString());
+ }
+ context.setTextMatrix( null);
+ context.setTextLineMatrix( null);
+ }
+
+}
diff --git a/src/main/java/org/pdfbox/util/operator/GRestore.java b/src/main/java/org/pdfbox/util/operator/GRestore.java
new file mode 100644
index 0000000..c07b8d8
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/GRestore.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import org.apache.log4j.Logger;
+import java.util.List;
+
+import org.pdfbox.pdmodel.graphics.PDGraphicsState;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ *
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class : the long sequence of
+ * conditions in processOperator is remplaced by this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.3 $
+ */
+public class GRestore extends OperatorProcessor
+{
+ private static final Logger LOG = Logger.getLogger(GRestore.class);
+
+
+ /**
+ * process : Q : Restore graphics state.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ if( LOG.isDebugEnabled() )
+ {
+ LOG.debug("<Q> - restore state" + this.toString());
+ }
+ context.setGraphicsState( (PDGraphicsState)context.getGraphicsStack().pop() );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/GSave.java b/src/main/java/org/pdfbox/util/operator/GSave.java
new file mode 100644
index 0000000..6a754b6
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/GSave.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ *
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class : the long sequence of
+ * conditions in processOperator is remplaced by this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.3 $
+ */
+
+public class GSave extends OperatorProcessor
+{
+ private static final Logger LOG = Logger.getLogger(GSave.class);
+
+ /**
+ * process : q : Save graphics state.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ if( LOG.isDebugEnabled() )
+ {
+ LOG.debug("<q> - save state " + this.toString());
+ }
+ context.getGraphicsStack().push( context.getGraphicsState().clone() );
+ }
+
+}
diff --git a/src/main/java/org/pdfbox/util/operator/Invoke.java b/src/main/java/org/pdfbox/util/operator/Invoke.java
new file mode 100644
index 0000000..2f8f789
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/Invoke.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSName;
+import org.pdfbox.cos.COSStream;
+import org.pdfbox.pdmodel.PDPage;
+import org.pdfbox.pdmodel.PDResources;
+import org.pdfbox.pdmodel.graphics.xobject.PDXObject;
+import org.pdfbox.pdmodel.graphics.xobject.PDXObjectForm;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.Map;
+
+/**
+ * Invoke named XObject.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @author Mario Ivankovits
+ *
+ * @version $Revision: 1.6 $
+ */
+public class Invoke extends OperatorProcessor
+{
+ private static final Logger LOG = Logger.getLogger(Invoke.class);
+
+ private Set inProcess = new TreeSet();
+
+ /**
+ * process : Do - Invoke a named xobject.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ *
+ * @throws IOException If there is an error processing this operator.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ COSName name = (COSName) arguments.get( 0 );
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("<Do name=\"" + name.getName() + "\">");
+ }
+
+ // wprinz: allow recursive processing so that nested xobject forms are correctly dealt with
+// if (inProcess.contains(name))
+// {
+// // avoid recursive loop
+// return;
+// }
+ // /wprinz
+
+ inProcess.add(name);
+
+ try
+ {
+ //PDResources res = context.getResources();
+
+ Map xobjects = context.getXObjects();
+ PDXObject xobject = (PDXObject) xobjects.get(name.getName());
+
+ if(xobject instanceof PDXObjectForm)
+ {
+ PDXObjectForm form = (PDXObjectForm)xobject;
+ COSStream invoke = (COSStream)form.getCOSObject();
+ PDResources pdResources = form.getResources();
+ PDPage page = context.getCurrentPage();
+ if(pdResources == null)
+ {
+ pdResources = page.findResources();
+ }
+
+ getContext().processSubStream( page, pdResources, invoke );
+ }
+ }
+ finally
+ {
+ inProcess.remove(name);
+ }
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/MoveAndShow.java b/src/main/java/org/pdfbox/util/operator/MoveAndShow.java
new file mode 100644
index 0000000..ca3a3f9
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/MoveAndShow.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSString;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class :
+* the long sequence of conditions in processOperator is remplaced by
+* this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.4 $
+ */
+public class MoveAndShow extends OperatorProcessor
+{
+
+ private static final Logger LOG = Logger.getLogger(MoveAndShow.class);
+
+ /**
+ * ' Move to next line and show text.
+ * @param arguments List
+ * @param operator The operator that is being executed.
+ * @throws IOException If there is an error processing the operator.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ // Move to start of next text line, and show text
+ //
+ if( LOG.isDebugEnabled())
+ {
+ COSString string = (COSString)arguments.get( 0 );
+ LOG.debug("<' string=\"" + string.getString() + "\">");
+ }
+
+ context.processOperator("T*", null);
+ context.processOperator("Tj", arguments);
+ }
+
+}
diff --git a/src/main/java/org/pdfbox/util/operator/MoveText.java b/src/main/java/org/pdfbox/util/operator/MoveText.java
new file mode 100644
index 0000000..10360bb
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/MoveText.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.Matrix;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ *
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class :
+ * the long sequence of conditions in processOperator is remplaced by
+ * this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.3 $
+ */
+public class MoveText extends OperatorProcessor
+{
+ private static final Logger LOG = Logger.getLogger(MoveText.class);
+
+
+ /**
+ * process : Td : Move text position.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ COSNumber x = (COSNumber)arguments.get( 0 );
+ COSNumber y = (COSNumber)arguments.get( 1 );
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("<Td x=\"" + x.floatValue() + "\" y=\"" + 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 );
+ context.setTextLineMatrix( td.multiply( context.getTextLineMatrix() ) ); //textLineMatrix.multiply( td );
+ //log.debug( "textLineMatrix after " + textLineMatrix );
+ context.setTextMatrix( context.getTextLineMatrix().copy() );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/MoveTextSetLeading.java b/src/main/java/org/pdfbox/util/operator/MoveTextSetLeading.java
new file mode 100644
index 0000000..e68a1d1
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/MoveTextSetLeading.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSFloat;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ *
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class :
+ * the long sequence of conditions in processOperator is remplaced by
+ * this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.4 $
+ */
+public class MoveTextSetLeading extends OperatorProcessor
+{
+
+ private static final Logger LOG = Logger.getLogger(MoveTextSetLeading.class);
+
+ /**
+ * process : TD Move text position and set leading.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ *
+ * @throws IOException If there is an error during processing.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ //move text position and set leading
+ COSNumber y = (COSNumber)arguments.get( 1 );
+ if (LOG.isDebugEnabled())
+ {
+ COSNumber x = (COSNumber)arguments.get( 0 );
+ LOG.debug("<TD x=\"" + x.floatValue() + "\" y=\"" + y.floatValue() + "\">");
+ }
+
+ ArrayList args = new ArrayList();
+ args.add(new COSFloat(-1*y.floatValue()));
+ context.processOperator("TL", args);
+ context.processOperator("Td", arguments);
+
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/NextLine.java b/src/main/java/org/pdfbox/util/operator/NextLine.java
new file mode 100644
index 0000000..daa35eb
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/NextLine.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import org.apache.log4j.Logger;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.pdfbox.cos.COSFloat;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ *
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class : the long sequence of
+ * conditions in processOperator is remplaced by this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.4 $
+ */
+public class NextLine extends OperatorProcessor
+{
+
+ private static final Logger LOG = Logger.getLogger(NextLine.class);
+
+ /**
+ * process : T* Move to start of next text line.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ *
+ * @throws IOException If there is an error during processing.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("<T* graphicsState.getTextState().getLeading()=\"" +
+ context.getGraphicsState().getTextState().getLeading() + "\">");
+ }
+ //move to start of next text line
+ ArrayList args = new ArrayList();
+ args.add(new COSFloat(0.0f));
+ // this must be -leading instead of just leading as written in the
+ // specification (p.369) the acrobat reader seems to implement it the same way
+ args.add(new COSFloat(-1*context.getGraphicsState().getTextState().getLeading()));
+ // use Td instead of repeating code
+ context.processOperator("Td", args);
+
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/OperatorProcessor.java b/src/main/java/org/pdfbox/util/operator/OperatorProcessor.java
new file mode 100644
index 0000000..27c21b9
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/OperatorProcessor.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.util.PDFStreamEngine;
+import java.util.List;
+import java.io.IOException;
+
+/**
+ *
+ * <p>Titre : OperatorProcessor</p>
+ * <p>Description : This class is the strategy abstract class
+ * in the strategy GOF pattern. After instancated, you must ever call
+* the setContext method to initiamise OPeratorProcessor</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.3 $
+ */
+public abstract class OperatorProcessor
+{
+
+ /**
+ * The stream engine processing context.
+ */
+ protected PDFStreamEngine context = null;
+
+ /**
+ * Constructor.
+ *
+ */
+ protected OperatorProcessor()
+ {
+ }
+
+ /**
+ * Get the context for processing.
+ *
+ * @return The processing context.
+ */
+ protected PDFStreamEngine getContext()
+ {
+ return context;
+ }
+
+ /**
+ * Set the processing context.
+ *
+ * @param ctx The context for processing.
+ */
+ public void setContext(PDFStreamEngine ctx)
+ {
+ context = ctx;
+ }
+
+ /**
+ * process the operator.
+ * @param operator The operator that is being processed.
+ * @param arguments arguments needed by this operator.
+ *
+ * @throws IOException If there is an error processing the operator.
+ */
+ public abstract void process(PDFOperator operator, List arguments) throws IOException;
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetCharSpacing.java b/src/main/java/org/pdfbox/util/operator/SetCharSpacing.java
new file mode 100644
index 0000000..6813dce
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetCharSpacing.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ *
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class :
+ * the long sequence of conditions in processOperator is remplaced by
+ * this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.4 $
+ */
+public class SetCharSpacing extends OperatorProcessor
+{
+
+ private static final Logger LOG = Logger.getLogger(SetCharSpacing.class);
+
+ /**
+ * process : Tc Set character spacing.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ //set character spacing
+ if( arguments.size() > 0 )
+ {
+ //There are some documents which are incorrectly structured, and have
+ //a wrong number of arguments to this, so we will assume the last argument
+ //in the list
+ Object charSpacing = arguments.get( arguments.size()-1 );
+ if( charSpacing instanceof COSNumber )
+ {
+ COSNumber characterSpacing = (COSNumber)charSpacing;
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("<Tc characterSpacing=\"" + characterSpacing.floatValue() + "\" />");
+ }
+ context.getGraphicsState().getTextState().setCharacterSpacing( characterSpacing.floatValue() );
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetGraphicsStateParameters.java b/src/main/java/org/pdfbox/util/operator/SetGraphicsStateParameters.java
new file mode 100644
index 0000000..e72e05d
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetGraphicsStateParameters.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSName;
+import org.pdfbox.pdmodel.graphics.PDExtendedGraphicsState;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Structal modification of the PDFEngine class :
+ * the long sequence of conditions in processOperator is remplaced by
+ * this strategy pattern.</p>
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.3 $
+ */
+
+public class SetGraphicsStateParameters extends OperatorProcessor
+{
+ private static final Logger LOG = Logger.getLogger(SetTextFont.class);
+
+ /**
+ * gs Set parameters from graphics state parameter dictionary.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ //set parameters from graphics state parameter dictionary
+ COSName graphicsName = (COSName)arguments.get( 0 );
+
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("<gs name=\"" + graphicsName.getName() + "\" />" );
+ }
+ PDExtendedGraphicsState gs = (PDExtendedGraphicsState)context.getGraphicsStates().get( graphicsName.getName() );
+ gs.copyIntoGraphicsState( context.getGraphicsState() );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetHorizontalTextScaling.java b/src/main/java/org/pdfbox/util/operator/SetHorizontalTextScaling.java
new file mode 100644
index 0000000..bfb9ebe
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetHorizontalTextScaling.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Structal modification of the PDFEngine class :
+ * the long sequence of conditions in processOperator is remplaced by
+ * this strategy pattern.</p>
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.3 $
+ */
+
+public class SetHorizontalTextScaling extends OperatorProcessor
+{
+ private static final Logger LOG = Logger.getLogger(SetTextFont.class);
+
+ /**
+ * Tz Set horizontal text scaling.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ COSNumber scaling = (COSNumber)arguments.get(0);
+ context.getGraphicsState().getTextState().setHorizontalScalingPercent( scaling.floatValue() );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetLineWidth.java b/src/main/java/org/pdfbox/util/operator/SetLineWidth.java
new file mode 100644
index 0000000..de0576d
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetLineWidth.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Structal modification of the PDFEngine class :
+ * the long sequence of conditions in processOperator is remplaced by
+ * this strategy pattern.</p>
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.3 $
+ */
+
+public class SetLineWidth extends OperatorProcessor
+{
+ private static final Logger LOG = Logger.getLogger(SetTextFont.class);
+
+ /**
+ * w Set line width.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ COSNumber width = (COSNumber)arguments.get( 0 );
+ context.getGraphicsState().setLineWidth( width.doubleValue() );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetMatrix.java b/src/main/java/org/pdfbox/util/operator/SetMatrix.java
new file mode 100644
index 0000000..5d5f1f5
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetMatrix.java
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.Matrix;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class : the long sequence of conditions
+ * in processOperator is remplaced by this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.3 $
+ */
+
+public class SetMatrix extends OperatorProcessor
+{
+
+ private static final Logger LOG = Logger.getLogger(SetMatrix.class);
+
+ /**
+ * Tm Set text matrix and text line matrix.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ //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("<Tm " +
+ "a=\"" + a.floatValue() + "\" " +
+ "b=\"" + b.floatValue() + "\" " +
+ "c=\"" + c.floatValue() + "\" " +
+ "d=\"" + d.floatValue() + "\" " +
+ "e=\"" + e.floatValue() + "\" " +
+ "f=\"" + f.floatValue() + "\" >");
+ }
+
+ Matrix 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() );
+ context.setTextMatrix( textMatrix );
+ context.setTextLineMatrix( textMatrix.copy() );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetMoveAndShow.java b/src/main/java/org/pdfbox/util/operator/SetMoveAndShow.java
new file mode 100644
index 0000000..b49206d
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetMoveAndShow.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.cos.COSString;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class : the long sequence of conditions
+ * in processOperator is remplaced by this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.5 $
+ */
+
+public class SetMoveAndShow extends OperatorProcessor
+{
+
+ private static final Logger LOG = Logger.getLogger(SetMoveAndShow.class);
+
+ /**
+ * " Set word and character spacing, move to next line, and show text.
+ * @param operator The operator that is being executed.
+ * @param arguments List.
+ * @throws IOException If there is an error processing the operator.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ //Set word and character spacing, move to next line, and show text
+ //
+ if (LOG.isDebugEnabled())
+ {
+ COSNumber wordSpacing = (COSNumber)arguments.get( 0 );
+ COSNumber characterSpacing = (COSNumber)arguments.get( 1 );
+ COSString string = (COSString)arguments.get( 2 );
+ LOG.debug("<\" wordSpacing=\"" + wordSpacing +
+ "\", characterSpacing=\"" + characterSpacing +
+ "\", string=\"" + string.getString() + "\">");
+ }
+
+ context.processOperator("Tw", arguments.subList(0,1));
+ context.processOperator("Tc", arguments.subList(1,2));
+ context.processOperator("'", arguments.subList(2,3));
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetNonStrokingCMYKColor.java b/src/main/java/org/pdfbox/util/operator/SetNonStrokingCMYKColor.java
new file mode 100644
index 0000000..941fcd6
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetNonStrokingCMYKColor.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance;
+import org.pdfbox.pdmodel.graphics.color.PDDeviceCMYK;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Set the non stroking color space.</p>
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.2 $
+ */
+public class SetNonStrokingCMYKColor extends OperatorProcessor
+{
+ /**
+ * cs Set color space for non stroking operations.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ PDColorSpace cs = PDDeviceCMYK.INSTANCE;
+ PDColorSpaceInstance colorInstance = context.getGraphicsState().getNonStrokingColorSpace();
+ colorInstance.setColorSpace( cs );
+ float[] values = new float[4];
+ for( int i=0; i<arguments.size(); i++ )
+ {
+ values[i] = ((COSNumber)arguments.get( i )).floatValue();
+ }
+ colorInstance.setColorSpaceValue( values );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetNonStrokingColorSpace.java b/src/main/java/org/pdfbox/util/operator/SetNonStrokingColorSpace.java
new file mode 100644
index 0000000..c75d1a4
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetNonStrokingColorSpace.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.pdfbox.cos.COSName;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpaceFactory;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance;
+import org.pdfbox.pdmodel.graphics.color.PDDeviceCMYK;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Set the non stroking color space.</p>
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.2 $
+ */
+public class SetNonStrokingColorSpace extends OperatorProcessor
+{
+ private static final float[] EMPTY_FLOAT_ARRAY = new float[0];
+
+ /**
+ * cs Set color space for non stroking operations.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+// (PDF 1.1) Set color space for stroking operations
+ COSName name = (COSName)arguments.get( 0 );
+ PDColorSpace cs = (PDColorSpace)context.getColorSpaces().get( name.getName() );
+ if( cs == null )
+ {
+ cs = PDColorSpaceFactory.createColorSpace( name );
+ }
+ PDColorSpaceInstance colorInstance = context.getGraphicsState().getNonStrokingColorSpace();
+ colorInstance.setColorSpace( cs );
+ int numComponents = cs.getNumberOfComponents();
+ float[] values = EMPTY_FLOAT_ARRAY;
+ if( numComponents >= 0 )
+ {
+ values = new float[numComponents];
+ for( int i=0; i<numComponents; i++ )
+ {
+ values[i] = 0f;
+ }
+ if( cs instanceof PDDeviceCMYK )
+ {
+ values[3] = 1f;
+ }
+ }
+ colorInstance.setColorSpaceValue( values );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetNonStrokingRGBColor.java b/src/main/java/org/pdfbox/util/operator/SetNonStrokingRGBColor.java
new file mode 100644
index 0000000..ca4e8b9
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetNonStrokingRGBColor.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance;
+import org.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Set the non stroking color space.</p>
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.2 $
+ */
+public class SetNonStrokingRGBColor extends OperatorProcessor
+{
+ /**
+ * rg Set color space for non stroking operations.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ PDColorSpace cs = PDDeviceRGB.INSTANCE;
+ PDColorSpaceInstance colorInstance = context.getGraphicsState().getNonStrokingColorSpace();
+ colorInstance.setColorSpace( cs );
+ float[] values = new float[3];
+ for( int i=0; i<arguments.size(); i++ )
+ {
+ values[i] = ((COSNumber)arguments.get( i )).floatValue();
+ }
+ colorInstance.setColorSpaceValue( values );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetStrokingCMYKColor.java b/src/main/java/org/pdfbox/util/operator/SetStrokingCMYKColor.java
new file mode 100644
index 0000000..5a03d83
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetStrokingCMYKColor.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance;
+import org.pdfbox.pdmodel.graphics.color.PDDeviceCMYK;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Structal modification of the PDFEngine class :
+ * the long sequence of conditions in processOperator is remplaced by
+ * this strategy pattern.</p>
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.2 $
+ */
+public class SetStrokingCMYKColor extends OperatorProcessor
+{
+ /**
+ * CS Set color space for stroking operations.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ PDColorSpace cs = PDDeviceCMYK.INSTANCE;
+ PDColorSpaceInstance colorInstance = context.getGraphicsState().getStrokingColorSpace();
+ colorInstance.setColorSpace( cs );
+ float[] values = new float[4];
+ for( int i=0; i<arguments.size(); i++ )
+ {
+ values[i] = ((COSNumber)arguments.get( i )).floatValue();
+ }
+ colorInstance.setColorSpaceValue( values );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetStrokingColorSpace.java b/src/main/java/org/pdfbox/util/operator/SetStrokingColorSpace.java
new file mode 100644
index 0000000..66d5bbc
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetStrokingColorSpace.java
@@ -0,0 +1,89 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.pdfbox.cos.COSName;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpaceFactory;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance;
+import org.pdfbox.pdmodel.graphics.color.PDDeviceCMYK;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Structal modification of the PDFEngine class :
+ * the long sequence of conditions in processOperator is remplaced by
+ * this strategy pattern.</p>
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.3 $
+ */
+
+public class SetStrokingColorSpace extends OperatorProcessor
+{
+ private static final float[] EMPTY_FLOAT_ARRAY = new float[0];
+
+ /**
+ * CS Set color space for stroking operations.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ //(PDF 1.1) Set color space for stroking operations
+ COSName name = (COSName)arguments.get( 0 );
+ PDColorSpace cs = (PDColorSpace)context.getColorSpaces().get( name.getName() );
+ if( cs == null )
+ {
+ cs = PDColorSpaceFactory.createColorSpace( name );
+ }
+ PDColorSpaceInstance colorInstance = context.getGraphicsState().getStrokingColorSpace();
+ colorInstance.setColorSpace( cs );
+ int numComponents = cs.getNumberOfComponents();
+ float[] values = EMPTY_FLOAT_ARRAY;
+ if( numComponents >= 0 )
+ {
+ values = new float[numComponents];
+ for( int i=0; i<numComponents; i++ )
+ {
+ values[i] = 0f;
+ }
+ if( cs instanceof PDDeviceCMYK )
+ {
+ values[3] = 1f;
+ }
+ }
+ colorInstance.setColorSpaceValue( values );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetStrokingRGBColor.java b/src/main/java/org/pdfbox/util/operator/SetStrokingRGBColor.java
new file mode 100644
index 0000000..1b66445
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetStrokingRGBColor.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance;
+import org.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Structal modification of the PDFEngine class :
+ * the long sequence of conditions in processOperator is remplaced by
+ * this strategy pattern.</p>
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.2 $
+ */
+public class SetStrokingRGBColor extends OperatorProcessor
+{
+ /**
+ * RG Set color space for stroking operations.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ PDColorSpace cs = PDDeviceRGB.INSTANCE;
+ PDColorSpaceInstance colorInstance = context.getGraphicsState().getStrokingColorSpace();
+ colorInstance.setColorSpace( cs );
+ float[] values = new float[3];
+ for( int i=0; i<arguments.size(); i++ )
+ {
+ values[i] = ((COSNumber)arguments.get( i )).floatValue();
+ }
+ colorInstance.setColorSpaceValue( values );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetTextFont.java b/src/main/java/org/pdfbox/util/operator/SetTextFont.java
new file mode 100644
index 0000000..3e54943
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetTextFont.java
@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSName;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.pdmodel.font.PDFont;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class :
+ * the long sequence of conditions in processOperator is remplaced by
+ * this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.4 $
+ */
+
+public class SetTextFont extends OperatorProcessor
+{
+ private static final Logger LOG = Logger.getLogger(SetTextFont.class);
+
+ /**
+ * Tf selectfont Set text font and size.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ //there are some documents that are incorrectly structured and
+ //arguments are in the wrong spot, so we will silently ignore them
+ //if there are no arguments
+ if( arguments.size() >= 2 )
+ {
+ //set font and size
+ COSName fontName = (COSName)arguments.get( 0 );
+ float fontSize = ((COSNumber)arguments.get( 1 ) ).floatValue();
+ context.getGraphicsState().getTextState().setFontSize( fontSize );
+
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("<Tf font=\"" + fontName.getName() + "\" size=\"" +
+ context.getGraphicsState().getTextState().getFontSize() + "\">");
+ }
+
+ //old way
+ //graphicsState.getTextState().getFont() = (COSObject)stream.getDictionaryObject( fontName );
+ //if( graphicsState.getTextState().getFont() == null )
+ //{
+ // graphicsState.getTextState().getFont() = (COSObject)graphicsState.getTextState().getFont()
+ // Dictionary.getItem( fontName );
+ //}
+ context.getGraphicsState().getTextState().setFont( (PDFont)context.getFonts().get( fontName.getName() ) );
+ if( context.getGraphicsState().getTextState().getFont() == null )
+ {
+ throw new IOException( "Error: Could not find font(" + fontName + ") in map=" + context.getFonts() );
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetTextLeading.java b/src/main/java/org/pdfbox/util/operator/SetTextLeading.java
new file mode 100644
index 0000000..928172b
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetTextLeading.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class :
+* the long sequence of conditions in processOperator is remplaced
+* by this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.3 $
+ */
+
+public class SetTextLeading extends OperatorProcessor
+{
+
+ private static final Logger LOG = Logger.getLogger(SetTextLeading.class);
+
+ /**
+ * TL Set text leading.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ COSNumber leading = (COSNumber)arguments.get( 0 );
+ context.getGraphicsState().getTextState().setLeading( leading.floatValue() );
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("<TL leading=\"" + leading.floatValue() + "\" >");
+ }
+ }
+
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetTextRenderingMode.java b/src/main/java/org/pdfbox/util/operator/SetTextRenderingMode.java
new file mode 100644
index 0000000..19da1e2
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetTextRenderingMode.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Structal modification of the PDFEngine class :
+ * the long sequence of conditions in processOperator is remplaced by
+ * this strategy pattern.</p>
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.3 $
+ */
+
+public class SetTextRenderingMode extends OperatorProcessor
+{
+ private static final Logger LOG = Logger.getLogger(SetTextFont.class);
+
+ /**
+ * Tr Set text rendering mode.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ COSNumber mode = (COSNumber)arguments.get( 0 );
+ context.getGraphicsState().getTextState().setRenderingMode( mode.intValue() );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetTextRise.java b/src/main/java/org/pdfbox/util/operator/SetTextRise.java
new file mode 100644
index 0000000..0d1e884
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetTextRise.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Structal modification of the PDFEngine class :
+ * the long sequence of conditions in processOperator is remplaced by
+ * this strategy pattern.</p>
+ *
+ * @author Ben Litchfield (ben@csh.rit.edu)
+ * @version $Revision: 1.3 $
+ */
+
+public class SetTextRise extends OperatorProcessor
+{
+ private static final Logger LOG = Logger.getLogger(SetTextFont.class);
+
+ /**
+ * Ts Set text rise.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ COSNumber rise = (COSNumber)arguments.get(0);
+ context.getGraphicsState().getTextState().setRise( rise.floatValue() );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/SetWordSpacing.java b/src/main/java/org/pdfbox/util/operator/SetWordSpacing.java
new file mode 100644
index 0000000..3a1e176
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/SetWordSpacing.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class : the long sequence of
+ * conditions in processOperator is remplaced by this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.3 $
+ */
+
+public class SetWordSpacing extends OperatorProcessor
+{
+ private static final Logger LOG = Logger.getLogger(SetWordSpacing.class);
+
+ /**
+ * Tw Set word spacing.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ //set word spacing
+ COSNumber wordSpacing = (COSNumber)arguments.get( 0 );
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("<Tw wordSpacing=\"" + wordSpacing.floatValue() + "\" />");
+ }
+ context.getGraphicsState().getTextState().setWordSpacing( wordSpacing.floatValue() );
+ }
+
+}
diff --git a/src/main/java/org/pdfbox/util/operator/ShowText.java b/src/main/java/org/pdfbox/util/operator/ShowText.java
new file mode 100644
index 0000000..1889259
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/ShowText.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSString;
+import org.pdfbox.util.PDFOperator;
+
+import java.io.IOException;
+
+/**
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class :
+ * the long sequence of conditions in processOperator
+ * is remplaced by this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.3 $
+ */
+
+public class ShowText extends OperatorProcessor
+{
+
+ private static final Logger LOG = Logger.getLogger(ShowText.class);
+
+ /**
+ * Tj show Show text.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ *
+ * @throws IOException If there is an error processing this operator.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ COSString string = (COSString)arguments.get( 0 );
+ context.showString( string.getBytes() );
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("<Tj string=\"" + string.getString() + "\">");
+ }
+ }
+
+}
diff --git a/src/main/java/org/pdfbox/util/operator/ShowTextGlyph.java b/src/main/java/org/pdfbox/util/operator/ShowTextGlyph.java
new file mode 100644
index 0000000..cf22e11
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/ShowTextGlyph.java
@@ -0,0 +1,99 @@
+/**
+ * Copyright (c) 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.util.operator;
+
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.pdfbox.util.Matrix;
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.cos.COSArray;
+import org.pdfbox.cos.COSBase;
+import org.pdfbox.cos.COSNumber;
+import java.io.IOException;
+import org.pdfbox.cos.COSString;
+
+/**
+ * <p>Titre : PDFEngine Modification.</p>
+ * <p>Description : Structal modification of the PDFEngine class : the long sequence of
+ * conditions in processOperator is remplaced by this strategy pattern</p>
+ * <p>Copyright : Copyright (c) 2004</p>
+ * <p>Société : DBGS</p>
+ * @author Huault : huault@free.fr
+ * @version $Revision: 1.5 $
+ */
+
+public class ShowTextGlyph extends OperatorProcessor
+{
+ private static final Logger LOG = Logger.getLogger(ShowTextGlyph.class);
+
+ /**
+ * TJ Show text, allowing individual glyph positioning.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If there is an error processing this operator.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ COSArray array = (COSArray)arguments.get( 0 );
+ float adjustment=0;
+ for( int i=0; i<array.size(); i++ )
+ {
+ COSBase next = array.get( i );
+ if( next instanceof COSNumber )
+ {
+ adjustment = ((COSNumber)next).floatValue();
+
+ Matrix adjMatrix = new Matrix();
+ adjustment=(-adjustment/1000)*context.getGraphicsState().getTextState().getFontSize() *
+ (context.getGraphicsState().getTextState().getHorizontalScalingPercent()/100);
+ adjMatrix.setValue( 2, 0, adjustment );
+ if( LOG.isDebugEnabled() )
+ {
+ LOG.debug( "TJ adjustment=" + adjustment + " textMatrix=" + context.getTextMatrix() );
+ }
+ context.setTextMatrix( adjMatrix.multiply( context.getTextMatrix() ) );
+ if( LOG.isDebugEnabled() )
+ {
+ LOG.debug( "textMatrix after=" + context.getTextMatrix() );
+ }
+ }
+ else if( next instanceof COSString )
+ {
+ context.showString( ((COSString)next).getBytes() );
+ }
+ else
+ {
+ throw new IOException( "Unknown type in array for TJ operation:" + next );
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/org/pdfbox/util/operator/package.html b/src/main/java/org/pdfbox/util/operator/package.html
new file mode 100644
index 0000000..edb8444
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/package.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+
+</head>
+<body>
+This package contains implementations of all of the PDF operators.
+</body>
+</html>
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/AppendRectangleToPath.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/AppendRectangleToPath.java
new file mode 100644
index 0000000..7d2d49f
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/AppendRectangleToPath.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.awt.geom.Rectangle2D;
+import java.util.List;
+
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.util.operator.OperatorProcessor;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class AppendRectangleToPath extends OperatorProcessor
+{
+
+
+ /**
+ * process : re : append rectangle to path.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ PageDrawer drawer = (PageDrawer)context;
+
+ COSNumber x = (COSNumber)arguments.get( 0 );
+ COSNumber y = (COSNumber)arguments.get( 1 );
+ COSNumber w = (COSNumber)arguments.get( 2 );
+ COSNumber h = (COSNumber)arguments.get( 3 );
+ Rectangle2D rect = new Rectangle2D.Double(
+ x.doubleValue(),
+ drawer.fixY( x.doubleValue(), y.doubleValue())-h.doubleValue(),
+ w.doubleValue()+1,
+ h.doubleValue()+1);
+ drawer.getLinePath().reset();
+
+ drawer.getLinePath().append( rect, false );
+ //graphics.drawRect((int)x.doubleValue(), (int)(pageSize.getHeight() - y.doubleValue()),
+ // (int)w.doubleValue(),(int)h.doubleValue() );
+ //System.out.println( "<re x=\"" + x.getValue() + "\" y=\"" + y.getValue() + "\" width=\"" +
+ // width.getValue() + "\" height=\"" + height.getValue() + "\" >" );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/BeginInlineImage.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/BeginInlineImage.java
new file mode 100644
index 0000000..9031345
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/BeginInlineImage.java
@@ -0,0 +1,114 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.List;
+
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.pdmodel.graphics.xobject.PDInlinedImage;
+import org.pdfbox.util.ImageParameters;
+import org.pdfbox.util.Matrix;
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.util.operator.OperatorProcessor;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class BeginInlineImage extends OperatorProcessor
+{
+
+
+ /**
+ * process : BI : begin inline image.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If there is an error displaying the inline image.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ PageDrawer drawer = (PageDrawer)context;
+ Graphics2D graphics = drawer.getGraphics();
+ //begin inline image object
+ ImageParameters params = operator.getImageParameters();
+ PDInlinedImage image = new PDInlinedImage();
+ image.setImageParameters( params );
+ image.setImageData( operator.getImageData() );
+ BufferedImage awtImage = image.createImage();
+
+ Matrix ctm = drawer.getGraphicsState().getCurrentTransformationMatrix();
+
+ int width = awtImage.getWidth();
+ int height = awtImage.getHeight();
+
+
+ AffineTransform at = new AffineTransform(
+ ctm.getValue(0,0)/width,
+ ctm.getValue(0,1),
+ ctm.getValue(1,0),
+ ctm.getValue(1,1)/height,
+ ctm.getValue(2,0),
+ ctm.getValue(2,1)
+ );
+ //at.setToRotation((double)page.getRotation());
+
+
+ // The transformation should be done
+ // 1 - Translation
+ // 2 - Rotation
+ // 3 - Scale or Skew
+ //AffineTransform at = new AffineTransform();
+
+ // Translation
+ //at = new AffineTransform();
+ //at.setToTranslation((double)ctm.getValue(0,0),
+ // (double)ctm.getValue(0,1));
+
+ // Rotation
+ //AffineTransform toAdd = new AffineTransform();
+ //toAdd.setToRotation(1.5705);
+ //toAdd.setToRotation(ctm.getValue(2,0)*(Math.PI/180));
+ //at.concatenate(toAdd);
+
+ // Scale / Skew?
+ //toAdd.setToScale(width, height);
+ //at.concatenate(toAdd);
+ //at.setToScale( width, height );
+ graphics.drawImage( awtImage, at, null );
+ //graphics.drawImage( awtImage,0,0, width,height,null);
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/ClosePath.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/ClosePath.java
new file mode 100644
index 0000000..418af6d
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/ClosePath.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.util.List;
+
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.util.operator.OperatorProcessor;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class ClosePath extends OperatorProcessor
+{
+
+
+ /**
+ * process : h : Close path.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ PageDrawer drawer = (PageDrawer)context;
+ drawer.getLinePath().closePath();
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveTo.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveTo.java
new file mode 100644
index 0000000..c056b91
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveTo.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.util.List;
+
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.util.operator.OperatorProcessor;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class CurveTo extends OperatorProcessor
+{
+
+
+ /**
+ * process : c : Append curved segment to path.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ PageDrawer drawer = (PageDrawer)context;
+
+ COSNumber x1 = (COSNumber)arguments.get( 0 );
+ COSNumber y1 = (COSNumber)arguments.get( 1 );
+ COSNumber x2 = (COSNumber)arguments.get( 2 );
+ COSNumber y2 = (COSNumber)arguments.get( 3 );
+ COSNumber x3 = (COSNumber)arguments.get( 4 );
+ COSNumber y3 = (COSNumber)arguments.get( 5 );
+ float x1f = x1.floatValue();
+ float y1f = (float)drawer.fixY( x1f, y1.floatValue() );
+ float x2f = x2.floatValue();
+ float y2f = (float)drawer.fixY( x2f, y2.floatValue() );
+ float x3f = x3.floatValue();
+ float y3f = (float)drawer.fixY( x3f, y3.floatValue() );
+ drawer.getLinePath().curveTo(x1f,y1f,x2f,y2f,x3f,y3f);
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateFinalPoint.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateFinalPoint.java
new file mode 100644
index 0000000..670cdb3
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateFinalPoint.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.util.List;
+
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.util.operator.OperatorProcessor;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class CurveToReplicateFinalPoint extends OperatorProcessor
+{
+
+
+ /**
+ * process : y : Append curved segment to path (final point replicated).
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ PageDrawer drawer = (PageDrawer)context;
+
+ COSNumber x1 = (COSNumber)arguments.get( 0 );
+ COSNumber y1 = (COSNumber)arguments.get( 1 );
+ COSNumber x3 = (COSNumber)arguments.get( 2 );
+ COSNumber y3 = (COSNumber)arguments.get( 3 );
+ float x1f = x1.floatValue();
+ float y1f = (float)drawer.fixY( x1f, y1.floatValue() );
+ float x3f = x3.floatValue();
+ float y3f = (float)drawer.fixY( x3f, y3.floatValue() );
+ drawer.getLinePath().curveTo(x1f,y1f,x3f,y3f,x3f,y3f);
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateInitialPoint.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateInitialPoint.java
new file mode 100644
index 0000000..ff354d0
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateInitialPoint.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.util.List;
+
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.util.operator.OperatorProcessor;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class CurveToReplicateInitialPoint extends OperatorProcessor
+{
+
+
+ /**
+ * process : v : Append curved segment to path (initial point replicated).
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ PageDrawer drawer = (PageDrawer)context;
+
+ COSNumber x2 = (COSNumber)arguments.get( 0 );
+ COSNumber y2 = (COSNumber)arguments.get( 1 );
+ COSNumber x3 = (COSNumber)arguments.get( 2 );
+ COSNumber y3 = (COSNumber)arguments.get( 3 );
+ float x2f = x2.floatValue();
+ float y2f = (float)drawer.fixY( x2f, y2.floatValue() );
+ float x3f = x3.floatValue();
+ float y3f = (float)drawer.fixY( x3f, y3.floatValue() );
+
+ GeneralPath path = drawer.getLinePath();
+ Point2D currentPoint = path.getCurrentPoint();
+ float currentX = (float)currentPoint.getX();
+ float currentY = (float)currentPoint.getY();
+ drawer.getLinePath().curveTo(currentX,currentY,x2f,y2f,x3f,y3f);
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/FillEvenOddRule.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/FillEvenOddRule.java
new file mode 100644
index 0000000..da9e834
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/FillEvenOddRule.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.GeneralPath;
+import java.util.List;
+
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.util.operator.OperatorProcessor;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class FillEvenOddRule extends OperatorProcessor
+{
+
+
+ /**
+ * process : f* : fill path using even odd rule.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+// NOTE:changes here should probably also be made to FillNonZeroRule
+ PageDrawer drawer = (PageDrawer)context;
+ Graphics2D graphics = drawer.getGraphics();
+ //linePath.closePath();
+ graphics.setColor( drawer.getNonStrokingColor() );
+ drawer.getLinePath().setWindingRule( GeneralPath.WIND_EVEN_ODD );
+ graphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
+ //else
+ //{
+ graphics.fill( drawer.getLinePath() );
+ //}
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/FillNonZeroRule.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/FillNonZeroRule.java
new file mode 100644
index 0000000..56efa33
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/FillNonZeroRule.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.GeneralPath;
+import java.util.List;
+
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.util.operator.OperatorProcessor;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class FillNonZeroRule extends OperatorProcessor
+{
+
+
+ /**
+ * process : F/f : fill path using non zero winding rule.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ //NOTE:changes here should probably also be made to FillEvenOddRule
+ PageDrawer drawer = (PageDrawer)context;
+ Graphics2D graphics = drawer.getGraphics();
+ //linePath.closePath();
+ graphics.setColor( drawer.getNonStrokingColor() );
+ drawer.getLinePath().setWindingRule( GeneralPath.WIND_NON_ZERO );
+ graphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
+ //else
+ //{
+ graphics.fill( drawer.getLinePath() );
+ //}
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/Invoke.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/Invoke.java
new file mode 100644
index 0000000..3d99b74
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/Invoke.java
@@ -0,0 +1,180 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSName;
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.pdmodel.PDPage;
+import org.pdfbox.pdmodel.graphics.xobject.PDXObject;
+import org.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;
+import org.pdfbox.util.Matrix;
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.util.operator.OperatorProcessor;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class Invoke extends OperatorProcessor
+{
+ private static Logger log = Logger.getLogger( Invoke.class );
+
+ /**
+ * process : re : append rectangle to path.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If there is an error invoking the sub object.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ PageDrawer drawer = (PageDrawer)context;
+ PDPage page = drawer.getPage();
+ Dimension pageSize = drawer.getPageSize();
+ Graphics2D graphics = drawer.getGraphics();
+ COSName objectName = (COSName)arguments.get( 0 );
+ Map xobjects = drawer.getResources().getXObjects();
+ PDXObject xobject = (PDXObject)xobjects.get( objectName.getName() );
+ if( xobject instanceof PDXObjectImage )
+ {
+ PDXObjectImage image = (PDXObjectImage)xobject;
+ try
+ {
+ BufferedImage awtImage = image.getRGBImage();
+ Matrix ctm = drawer.getGraphicsState().getCurrentTransformationMatrix();
+
+ int width = awtImage.getWidth();
+ int height = awtImage.getHeight();
+
+ double rotationInRadians =(page.findRotation() * Math.PI)/180;
+
+
+ AffineTransform rotation = new AffineTransform();
+ rotation.setToRotation( rotationInRadians );
+ AffineTransform rotationInverse = rotation.createInverse();
+ Matrix rotationInverseMatrix = new Matrix();
+ rotationInverseMatrix.setFromAffineTransform( rotationInverse );
+ Matrix rotationMatrix = new Matrix();
+ rotationMatrix.setFromAffineTransform( rotation );
+
+ Matrix unrotatedCTM = ctm.multiply( rotationInverseMatrix );
+
+ Matrix scalingParams = unrotatedCTM.extractScaling();
+ Matrix scalingMatrix = Matrix.getScaleInstance(1f/width,1f/height);
+ scalingParams = scalingParams.multiply( scalingMatrix );
+
+ Matrix translationParams = unrotatedCTM.extractTranslating();
+ Matrix translationMatrix = null;
+ int pageRotation = page.findRotation();
+ if( pageRotation == 0 )
+ {
+ translationParams.setValue(2,1, -translationParams.getValue( 2,1 ));
+ translationMatrix = Matrix.getTranslatingInstance(
+ 0, (float)pageSize.getHeight()-height*scalingParams.getYScale() );
+ }
+ else if( pageRotation == 90 )
+ {
+ translationMatrix = Matrix.getTranslatingInstance( 0, (float)pageSize.getHeight() );
+ }
+ else
+ {
+ //TODO need to figure out other cases
+ }
+ translationParams = translationParams.multiply( translationMatrix );
+
+ AffineTransform at = new AffineTransform(
+ scalingParams.getValue( 0,0), 0,
+ 0, scalingParams.getValue( 1, 1),
+ translationParams.getValue(2,0), translationParams.getValue( 2,1 )
+ );
+
+
+
+
+ //at.setToTranslation( pageSize.getHeight()-ctm.getValue(2,0),ctm.getValue(2,1) );
+ //at.setToScale( ctm.getValue(0,0)/width, ctm.getValue(1,1)/height);
+ //at.setToRotation( (page.findRotation() * Math.PI)/180 );
+
+
+
+ //AffineTransform rotation = new AffineTransform();
+ //rotation.rotate( (90*Math.PI)/180);
+
+ /*
+
+ // The transformation should be done
+ // 1 - Translation
+ // 2 - Rotation
+ // 3 - Scale or Skew
+ AffineTransform at = new AffineTransform();
+
+ // Translation
+ at = new AffineTransform();
+ //at.setToTranslation((double)ctm.getValue(0,0),
+ // (double)ctm.getValue(0,1));
+
+ // Rotation
+ //AffineTransform toAdd = new AffineTransform();
+ toAdd.setToRotation(1.5705);
+ toAdd.setToRotation(ctm.getValue(2,0)*(Math.PI/180));
+ at.concatenate(toAdd);
+ */
+
+ // Scale / Skew?
+ //toAdd.setToScale(1, 1);
+ //at.concatenate(toAdd);
+
+ graphics.drawImage( awtImage, at, null );
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+ }
+ else
+ {
+ log.warn( "Unknown xobject type:" + xobject );
+ }
+
+
+ //invoke named object.
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/LineTo.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/LineTo.java
new file mode 100644
index 0000000..a70099b
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/LineTo.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.util.List;
+
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.util.operator.OperatorProcessor;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class LineTo extends OperatorProcessor
+{
+
+
+ /**
+ * process : l : Append straight line segment to path.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ PageDrawer drawer = (PageDrawer)context;
+
+ //append straight line segment from the current point to the point.
+ COSNumber x = (COSNumber)arguments.get( 0 );
+ COSNumber y = (COSNumber)arguments.get( 1 );
+
+ drawer.getLinePath().lineTo( x.floatValue(), (float)drawer.fixY( x.doubleValue(), y.doubleValue()) );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/MoveTo.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/MoveTo.java
new file mode 100644
index 0000000..e1c8f1e
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/MoveTo.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.awt.geom.GeneralPath;
+import java.util.List;
+
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.util.operator.OperatorProcessor;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class MoveTo extends OperatorProcessor
+{
+
+
+ /**
+ * process : m : Begin new subpath.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ */
+ public void process(PDFOperator operator, List arguments)
+ {
+ PageDrawer drawer = (PageDrawer)context;
+
+ COSNumber x = (COSNumber)arguments.get( 0 );
+ COSNumber y = (COSNumber)arguments.get( 1 );
+
+ drawer.getLineSubPaths().add( drawer.getLinePath() );
+ GeneralPath newPath = new GeneralPath();
+ newPath.moveTo( x.floatValue(), (float)drawer.fixY( x.doubleValue(), y.doubleValue()) );
+ drawer.setLinePath( newPath );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetLineWidth.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetLineWidth.java
new file mode 100644
index 0000000..4217451
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetLineWidth.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.util.List;
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.util.PDFOperator;
+
+import java.awt.BasicStroke;
+import java.io.IOException;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class SetLineWidth extends org.pdfbox.util.operator.SetLineWidth
+{
+
+ /**
+ * w Set line width.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ super.process( operator, arguments );
+ float lineWidth = (float)context.getGraphicsState().getLineWidth();
+ if( lineWidth == 0 )
+ {
+ lineWidth = 1;
+ }
+ ((PageDrawer)context).getGraphics().setStroke( new BasicStroke( lineWidth ) );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingCMYKColor.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingCMYKColor.java
new file mode 100644
index 0000000..d1c37fe
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingCMYKColor.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.util.List;
+
+import java.awt.Color;
+import java.io.IOException;
+
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class SetNonStrokingCMYKColor extends org.pdfbox.util.operator.SetNonStrokingCMYKColor
+{
+ /**
+ * k Set color space for non stroking operations.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ super.process( operator, arguments );
+ PageDrawer drawer = (PageDrawer)context;
+ PDColorSpaceInstance colorInstance = drawer.getGraphicsState().getNonStrokingColorSpace();
+ Color color = colorInstance.createColor();
+ drawer.setNonStrokingColor( color );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingColorSpace.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingColorSpace.java
new file mode 100644
index 0000000..e5abae8
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingColorSpace.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.util.List;
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance;
+import org.pdfbox.util.PDFOperator;
+
+
+import java.awt.Color;
+import java.io.IOException;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class SetNonStrokingColorSpace extends org.pdfbox.util.operator.SetNonStrokingColorSpace
+{
+ /**
+ * cs Set color space for non stroking operations.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ try
+ {
+ super.process( operator, arguments );
+ PageDrawer drawer = (PageDrawer)context;
+ PDColorSpaceInstance colorInstance = drawer.getGraphicsState().getNonStrokingColorSpace();
+ Color color = colorInstance.createColor();
+ drawer.setNonStrokingColor( color );
+ }
+ catch( IOException e )
+ {
+ //ignore for now and continue drawing
+ }
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingRGBColor.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingRGBColor.java
new file mode 100644
index 0000000..f816d1f
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingRGBColor.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.util.List;
+
+import java.awt.Color;
+import java.io.IOException;
+
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class SetNonStrokingRGBColor extends org.pdfbox.util.operator.SetNonStrokingRGBColor
+{
+ /**
+ * rg Set color space for non stroking operations.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ super.process( operator, arguments );
+ PageDrawer drawer = (PageDrawer)context;
+ COSNumber r = (COSNumber)arguments.get( 0 );
+ COSNumber g = (COSNumber)arguments.get( 1 );
+ COSNumber b = (COSNumber)arguments.get( 2 );
+ drawer.setNonStrokingColor( new Color( r.floatValue(), g.floatValue(), b.floatValue() ) );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingCMYKColor.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingCMYKColor.java
new file mode 100644
index 0000000..81fcef3
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingCMYKColor.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.util.List;
+
+import java.awt.Color;
+import java.io.IOException;
+
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class SetStrokingCMYKColor extends org.pdfbox.util.operator.SetStrokingCMYKColor
+{
+ /**
+ * CS Set color space for stroking operations.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ super.process( operator, arguments );
+ PageDrawer drawer = (PageDrawer)context;
+ PDColorSpaceInstance colorInstance = drawer.getGraphicsState().getNonStrokingColorSpace();
+ Color color = colorInstance.createColor();
+ drawer.setStrokingColor( color );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingColorSpace.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingColorSpace.java
new file mode 100644
index 0000000..22c9c5c
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingColorSpace.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.util.List;
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance;
+import org.pdfbox.util.PDFOperator;
+
+import java.awt.Color;
+import java.io.IOException;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class SetStrokingColorSpace extends org.pdfbox.util.operator.SetNonStrokingColorSpace
+{
+ /**
+ * CS Set color space for stroking operations.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ super.process( operator, arguments );
+ try
+ {
+ PageDrawer drawer = (PageDrawer)context;
+ PDColorSpaceInstance colorInstance = drawer.getGraphicsState().getNonStrokingColorSpace();
+ Color color = colorInstance.createColor();
+ drawer.setStrokingColor( color );
+ }
+ catch( IOException e )
+ {
+ //ignore for now and continue drawing
+ }
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingRGBColor.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingRGBColor.java
new file mode 100644
index 0000000..8d7099e
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingRGBColor.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.util.List;
+
+import java.awt.Color;
+import java.io.IOException;
+
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.util.PDFOperator;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class SetStrokingRGBColor extends org.pdfbox.util.operator.SetStrokingRGBColor
+{
+ /**
+ * RG Set color space for stroking operations.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ super.process( operator, arguments );
+ PageDrawer drawer = (PageDrawer)context;
+ COSNumber r = (COSNumber)arguments.get( 0 );
+ COSNumber g = (COSNumber)arguments.get( 1 );
+ COSNumber b = (COSNumber)arguments.get( 2 );
+ drawer.setStrokingColor( new Color( r.floatValue(), g.floatValue(), b.floatValue() ) );
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/StrokePath.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/StrokePath.java
new file mode 100644
index 0000000..31a489c
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/StrokePath.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 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.util.operator.pagedrawer;
+
+import java.util.List;
+import org.pdfbox.pdfviewer.PageDrawer;
+import org.pdfbox.util.PDFOperator;
+
+import java.awt.Graphics2D;
+import java.awt.geom.GeneralPath;
+import java.io.IOException;
+
+/**
+ * Implementation of content stream operator for page drawer.
+ *
+ * @author Ben Litchfield (ben@benlitchfield.com)
+ * @version $Revision: 1.1 $
+ */
+public class StrokePath extends org.pdfbox.util.operator.SetLineWidth
+{
+
+ /**
+ * S stroke the path.
+ * @param operator The operator that is being executed.
+ * @param arguments List
+ *
+ * @throws IOException If an error occurs while processing the font.
+ */
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ PageDrawer drawer = (PageDrawer)context;
+ Graphics2D graphics = ((PageDrawer)context).getGraphics();
+ graphics.setColor( drawer.getStrokingColor() );
+ List subPaths = drawer.getLineSubPaths();
+ for( int i=0; i<subPaths.size(); i++ )
+ {
+ GeneralPath subPath = (GeneralPath)subPaths.get( i );
+ graphics.draw( subPath );
+ }
+ subPaths.clear();
+ GeneralPath path = drawer.getLinePath();
+ graphics.draw( path );
+ path.reset();
+ }
+}
diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/package.html b/src/main/java/org/pdfbox/util/operator/pagedrawer/package.html
new file mode 100644
index 0000000..edb8444
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/package.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+
+</head>
+<body>
+This package contains implementations of all of the PDF operators.
+</body>
+</html>
diff --git a/src/main/java/org/pdfbox/util/package.html b/src/main/java/org/pdfbox/util/package.html
new file mode 100644
index 0000000..f8948fb
--- /dev/null
+++ b/src/main/java/org/pdfbox/util/package.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+
+</head>
+<body>
+This package contains utility classes that are used by the PDFBox project.
+</body>
+</html>