Home » pdfbox-1.1.0-src » org.apache.pdfbox.pdmodel.edit » [javadoc | source]

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   package org.apache.pdfbox.pdmodel.edit;
   18   
   19   import java.awt.Color;
   20   import java.awt.color.ColorSpace;
   21   import java.io.ByteArrayOutputStream;
   22   import java.io.IOException;
   23   import java.io.OutputStream;
   24   
   25   import java.text.NumberFormat;
   26   
   27   import java.util.ArrayList;
   28   import java.util.List;
   29   import java.util.Locale;
   30   import java.util.Map;
   31   import java.util.HashMap;
   32   
   33   import org.apache.pdfbox.pdmodel.PDDocument;
   34   import org.apache.pdfbox.pdmodel.PDPage;
   35   import org.apache.pdfbox.pdmodel.PDResources;
   36   
   37   import org.apache.pdfbox.pdmodel.common.COSStreamArray;
   38   import org.apache.pdfbox.pdmodel.common.PDStream;
   39   
   40   import org.apache.pdfbox.pdmodel.font.PDFont;
   41   import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
   42   import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceCMYK;
   43   import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceGray;
   44   import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceN;
   45   import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
   46   import org.apache.pdfbox.pdmodel.graphics.color.PDICCBased;
   47   import org.apache.pdfbox.pdmodel.graphics.color.PDPattern;
   48   import org.apache.pdfbox.pdmodel.graphics.color.PDSeparation;
   49   import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObject;
   50   import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;
   51   import org.apache.pdfbox.util.MapUtil;
   52   
   53   import org.apache.pdfbox.cos.COSArray;
   54   import org.apache.pdfbox.cos.COSDictionary;
   55   import org.apache.pdfbox.cos.COSName;
   56   import org.apache.pdfbox.cos.COSString;
   57   
   58   
   59   /**
   60    * This class will is a convenience for creating page content streams.  You MUST
   61    * call close() when you are finished with this object.
   62    *
   63    * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
   64    * @version $Revision: 1.19 $
   65    */
   66   public class PDPageContentStream
   67   {
   68       private PDPage page;
   69       private OutputStream output;
   70       private boolean inTextMode = false;
   71       private Map<PDFont,String> fontMappings = new HashMap<PDFont,String>();
   72       private Map<PDXObject,String> xobjectMappings = new HashMap<PDXObject,String>();
   73       private PDResources resources;
   74       private Map fonts;
   75       private Map xobjects;
   76   
   77       private PDColorSpace currentStrokingColorSpace = new PDDeviceGray();
   78       private PDColorSpace currentNonStrokingColorSpace = new PDDeviceGray();
   79   
   80       //cached storage component for getting color values
   81       private float[] colorComponents = new float[4];
   82   
   83       private NumberFormat formatDecimal = NumberFormat.getNumberInstance( Locale.US );
   84   
   85       private static final String BEGIN_TEXT = "BT\n";
   86       private static final String END_TEXT = "ET\n";
   87       private static final String SET_FONT = "Tf\n";
   88       private static final String MOVE_TEXT_POSITION = "Td\n";
   89       private static final String SET_TEXT_MATRIX = "Tm\n";
   90       private static final String SHOW_TEXT = "Tj\n";
   91   
   92       private static final String SAVE_GRAPHICS_STATE = "q\n";
   93       private static final String RESTORE_GRAPHICS_STATE = "Q\n";
   94       private static final String CONCATENATE_MATRIX = "cm\n";
   95       private static final String XOBJECT_DO = "Do\n";
   96       private static final String RG_STROKING = "RG\n";
   97       private static final String RG_NON_STROKING = "rg\n";
   98       private static final String K_STROKING = "K\n";
   99       private static final String K_NON_STROKING = "k\n";
  100       private static final String G_STROKING = "G\n";
  101       private static final String G_NON_STROKING = "g\n";
  102       private static final String APPEND_RECTANGLE = "re\n";
  103       private static final String FILL = "f\n";
  104       private static final String LINE_TO = "l\n";
  105       private static final String MOVE_TO = "m\n";
  106       private static final String STROKE = "S\n";
  107       private static final String LINE_WIDTH = "w\n";
  108   
  109   
  110       private static final String SET_STROKING_COLORSPACE = "CS\n";
  111       private static final String SET_NON_STROKING_COLORSPACE = "cs\n";
  112   
  113       private static final String SET_STROKING_COLOR_SIMPLE="SC\n";
  114       private static final String SET_STROKING_COLOR_COMPLEX="SCN\n";
  115       private static final String SET_NON_STROKING_COLOR_SIMPLE="sc\n";
  116       private static final String SET_NON_STROKING_COLOR_COMPLEX="scn\n";
  117   
  118   
  119   
  120       private static final int SPACE = 32;
  121   
  122   
  123       /**
  124        * Create a new PDPage content stream.
  125        *
  126        * @param document The document the page is part of.
  127        * @param sourcePage The page to write the contents to.
  128        * @throws IOException If there is an error writing to the page contents.
  129        */
  130       public PDPageContentStream( PDDocument document, PDPage sourcePage ) throws IOException
  131       {
  132           this(document,sourcePage,false,true);
  133       }
  134   
  135       /**
  136        * Create a new PDPage content stream.
  137        *
  138        * @param document The document the page is part of.
  139        * @param sourcePage The page to write the contents to.
  140        * @param appendContent Indicates whether content will be overwritten. If false all previous content is deleted.
  141        * @param compress Tell if the content stream should compress the page contents.
  142        * @throws IOException If there is an error writing to the page contents.
  143        */
  144       public PDPageContentStream( PDDocument document, PDPage sourcePage, boolean appendContent, boolean compress )
  145           throws IOException
  146       {
  147           page = sourcePage;
  148           resources = page.getResources();
  149           if( resources == null )
  150           {
  151               resources = new PDResources();
  152               page.setResources( resources );
  153           }
  154           fonts = resources.getFonts();
  155           xobjects = resources.getImages();
  156           // If request specifies the need to append to the document
  157           if(appendContent)
  158           {
  159               // Get the pdstream from the source page instead of creating a new one
  160               PDStream contents = sourcePage.getContents();
  161   
  162               // Create a pdstream to append new content
  163               PDStream contentsToAppend = new PDStream( document );
  164   
  165               // This will be the resulting COSStreamArray after existing and new streams are merged
  166               COSStreamArray compoundStream = null;
  167   
  168               // If contents is already an array, a new stream is simply appended to it
  169               if(contents.getStream() instanceof COSStreamArray)
  170               {
  171                   compoundStream = (COSStreamArray)contents.getStream();
  172                   compoundStream.appendStream( contentsToAppend.getStream());
  173               }
  174               else
  175               {
  176                   // Creates the COSStreamArray and adds the current stream plus a new one to it
  177                   COSArray newArray = new COSArray();
  178                   newArray.add(contents.getCOSObject());
  179                   newArray.add(contentsToAppend.getCOSObject());
  180                   compoundStream = new COSStreamArray(newArray);
  181               }
  182   
  183               if( compress )
  184               {
  185                   List filters = new ArrayList();
  186                   filters.add( COSName.FLATE_DECODE );
  187                   contentsToAppend.setFilters( filters );
  188               }
  189   
  190               // Sets the compoundStream as page contents
  191               sourcePage.setContents( new PDStream(compoundStream) );
  192               output = contentsToAppend.createOutputStream();
  193           }
  194           else
  195           {
  196               PDStream contents = new PDStream( document );
  197               if( compress )
  198               {
  199                   List filters = new ArrayList();
  200                   filters.add( COSName.FLATE_DECODE );
  201                   contents.setFilters( filters );
  202               }
  203               sourcePage.setContents( contents );
  204               output = contents.createOutputStream();
  205           }
  206           formatDecimal.setMaximumFractionDigits( 10 );
  207           formatDecimal.setGroupingUsed( false );
  208       }
  209   
  210       /**
  211        * Begin some text operations.
  212        *
  213        * @throws IOException If there is an error writing to the stream or if you attempt to
  214        *         nest beginText calls.
  215        */
  216       public void beginText() throws IOException
  217       {
  218           if( inTextMode )
  219           {
  220               throw new IOException( "Error: Nested beginText() calls are not allowed." );
  221           }
  222           appendRawCommands( BEGIN_TEXT );
  223           inTextMode = true;
  224       }
  225   
  226       /**
  227        * End some text operations.
  228        *
  229        * @throws IOException If there is an error writing to the stream or if you attempt to
  230        *         nest endText calls.
  231        */
  232       public void endText() throws IOException
  233       {
  234           if( !inTextMode )
  235           {
  236               throw new IOException( "Error: You must call beginText() before calling endText." );
  237           }
  238           appendRawCommands( END_TEXT );
  239           inTextMode = false;
  240       }
  241   
  242       /**
  243        * Set the font to draw text with.
  244        *
  245        * @param font The font to use.
  246        * @param fontSize The font size to draw the text.
  247        * @throws IOException If there is an error writing the font information.
  248        */
  249       public void setFont( PDFont font, float fontSize ) throws IOException
  250       {
  251           String fontMapping = fontMappings.get( font );
  252           if( fontMapping == null )
  253           {
  254               fontMapping = MapUtil.getNextUniqueKey( fonts, "F" );
  255               fontMappings.put( font, fontMapping );
  256               fonts.put( fontMapping, font );
  257           }
  258           appendRawCommands( "/");
  259           appendRawCommands( fontMapping );
  260           appendRawCommands( SPACE );
  261           appendRawCommands( formatDecimal.format( fontSize ) );
  262           appendRawCommands( SPACE );
  263           appendRawCommands( SET_FONT );
  264       }
  265   
  266       /**
  267        * Draw an image at the x,y coordinates, with the default size of the image.
  268        *
  269        * @param image The image to draw.
  270        * @param x The x-coordinate to draw the image.
  271        * @param y The y-coordinate to draw the image.
  272        *
  273        * @throws IOException If there is an error writing to the stream.
  274        */
  275       public void drawImage( PDXObjectImage image, float x, float y ) throws IOException
  276       {
  277           drawXObject( image, x, y, image.getWidth(), image.getHeight() );
  278       }
  279   
  280       /**
  281        * Draw an xobject(form or image) at the x,y coordinates and a certain width and height.
  282        *
  283        * @param xobject The xobject to draw.
  284        * @param x The x-coordinate to draw the image.
  285        * @param y The y-coordinate to draw the image.
  286        * @param width The width of the image to draw.
  287        * @param height The height of the image to draw.
  288        *
  289        * @throws IOException If there is an error writing to the stream.
  290        */
  291       public void drawXObject( PDXObject xobject, float x, float y, float width, float height ) throws IOException
  292       {
  293           String xObjectPrefix = null;
  294           if( xobject instanceof PDXObjectImage )
  295           {
  296               xObjectPrefix = "Im";
  297           }
  298           else
  299           {
  300               xObjectPrefix = "Form";
  301           }
  302   
  303           String objMapping = xobjectMappings.get( xobject );
  304           if( objMapping == null )
  305           {
  306               objMapping = MapUtil.getNextUniqueKey( xobjects, xObjectPrefix );
  307               xobjectMappings.put( xobject, objMapping );
  308               xobjects.put( objMapping, xobject );
  309           }
  310           appendRawCommands( SAVE_GRAPHICS_STATE );
  311           appendRawCommands( formatDecimal.format( width ) );
  312           appendRawCommands( SPACE );
  313           appendRawCommands( formatDecimal.format( 0 ) );
  314           appendRawCommands( SPACE );
  315           appendRawCommands( formatDecimal.format( 0 ) );
  316           appendRawCommands( SPACE );
  317           appendRawCommands( formatDecimal.format( height ) );
  318           appendRawCommands( SPACE );
  319           appendRawCommands( formatDecimal.format( x ) );
  320           appendRawCommands( SPACE );
  321           appendRawCommands( formatDecimal.format( y ) );
  322           appendRawCommands( SPACE );
  323           appendRawCommands( CONCATENATE_MATRIX );
  324           appendRawCommands( SPACE );
  325           appendRawCommands( "/" );
  326           appendRawCommands( objMapping );
  327           appendRawCommands( SPACE );
  328           appendRawCommands( XOBJECT_DO );
  329           appendRawCommands( SPACE );
  330           appendRawCommands( RESTORE_GRAPHICS_STATE );
  331       }
  332   
  333       /**
  334        * The Td operator.
  335        * A current text matrix will be replaced with a new one (1 0 0 1 x y). 
  336        * @param x The x coordinate.
  337        * @param y The y coordinate.
  338        * @throws IOException If there is an error writing to the stream.
  339        */
  340       public void moveTextPositionByAmount( float x, float y ) throws IOException
  341       {
  342           if( !inTextMode )
  343           {
  344               throw new IOException( "Error: must call beginText() before moveTextPositionByAmount");
  345           }
  346           appendRawCommands( formatDecimal.format( x ) );
  347           appendRawCommands( SPACE );
  348           appendRawCommands( formatDecimal.format( y ) );
  349           appendRawCommands( SPACE );
  350           appendRawCommands( MOVE_TEXT_POSITION );
  351       }
  352   
  353       /**
  354        * The Tm operator. Sets the text matrix to the given values.
  355        * A current text matrix will be replaced with the new one. 
  356        * @param a The a value of the matrix.
  357        * @param b The b value of the matrix.
  358        * @param c The c value of the matrix.
  359        * @param d The d value of the matrix.
  360        * @param e The e value of the matrix.
  361        * @param f The f value of the matrix.
  362        * @throws IOException If there is an error writing to the stream.
  363        */
  364       public void setTextMatrix( double a, double b, double c, double d, double e, double f ) throws IOException
  365       {
  366           if( !inTextMode )
  367           {
  368               throw new IOException( "Error: must call beginText() before setTextMatrix");
  369           }
  370           appendRawCommands( formatDecimal.format( a ) );
  371           appendRawCommands( SPACE );
  372           appendRawCommands( formatDecimal.format( b ) );
  373           appendRawCommands( SPACE );
  374           appendRawCommands( formatDecimal.format( c ) );
  375           appendRawCommands( SPACE );
  376           appendRawCommands( formatDecimal.format( d ) );
  377           appendRawCommands( SPACE );
  378           appendRawCommands( formatDecimal.format( e ) );
  379           appendRawCommands( SPACE );
  380           appendRawCommands( formatDecimal.format( f ) );
  381           appendRawCommands( SPACE );
  382           appendRawCommands( SET_TEXT_MATRIX );
  383       }
  384   
  385       /**
  386        * The Tm operator. Sets the text matrix to the given scaling and translation values.
  387        * A current text matrix will be replaced with the new one. 
  388        * @param sx The scaling factor in x-direction.
  389        * @param sy The scaling factor in y-direction.
  390        * @param tx The translation value in x-direction.
  391        * @param ty The translation value in y-direction.
  392        * @throws IOException If there is an error writing to the stream.
  393        */
  394       public void setTextScaling( double sx, double sy, double tx, double ty ) throws IOException
  395       {
  396           setTextMatrix(sx, 0, 0, sy, tx, ty);
  397       }
  398   
  399       /**
  400        * The Tm operator. Sets the text matrix to the given translation values.
  401        * A current text matrix will be replaced with the new one. 
  402        * @param tx The translation value in x-direction.
  403        * @param ty The translation value in y-direction.
  404        * @throws IOException If there is an error writing to the stream.
  405        */
  406       public void setTextTranslation( double tx, double ty ) throws IOException
  407       {
  408           setTextMatrix(1, 0, 0, 1, tx, ty);
  409       }
  410   
  411       /**
  412        * The Tm operator. Sets the text matrix to the given rotation and translation values.
  413        * A current text matrix will be replaced with the new one. 
  414        * @param angle The angle used for the counterclockwise rotation in radians.
  415        * @param tx The translation value in x-direction.
  416        * @param ty The translation value in y-direction.
  417        * @throws IOException If there is an error writing to the stream.
  418        */
  419       public void setTextRotation( double angle, double tx, double ty ) throws IOException
  420       {
  421           double angleCos = Math.cos(angle);
  422           double angleSin = Math.sin(angle);
  423           setTextMatrix( angleCos, angleSin, -angleSin, angleCos, tx, ty);
  424       }
  425   
  426       /**
  427        * This will draw a string at the current location on the screen.
  428        *
  429        * @param text The text to draw.
  430        * @throws IOException If an io exception occurs.
  431        */
  432       public void drawString( String text ) throws IOException
  433       {
  434           if( !inTextMode )
  435           {
  436               throw new IOException( "Error: must call beginText() before drawString");
  437           }
  438           COSString string = new COSString( text );
  439           ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  440           string.writePDF( buffer );
  441           appendRawCommands( new String( buffer.toByteArray(), "ISO-8859-1"));
  442           appendRawCommands( SPACE );
  443           appendRawCommands( SHOW_TEXT );
  444       }
  445   
  446       /**
  447        * Set the stroking color space.  This will add the colorspace to the PDResources
  448        * if necessary.
  449        *
  450        * @param colorSpace The colorspace to write.
  451        * @throws IOException If there is an error writing the colorspace.
  452        */
  453       public void setStrokingColorSpace( PDColorSpace colorSpace ) throws IOException
  454       {
  455           currentStrokingColorSpace = colorSpace;
  456           writeColorSpace( colorSpace );
  457           appendRawCommands( SET_STROKING_COLORSPACE );
  458       }
  459   
  460       /**
  461        * Set the stroking color space.  This will add the colorspace to the PDResources
  462        * if necessary.
  463        *
  464        * @param colorSpace The colorspace to write.
  465        * @throws IOException If there is an error writing the colorspace.
  466        */
  467       public void setNonStrokingColorSpace( PDColorSpace colorSpace ) throws IOException
  468       {
  469           currentNonStrokingColorSpace = colorSpace;
  470           writeColorSpace( colorSpace );
  471           appendRawCommands( SET_NON_STROKING_COLORSPACE );
  472       }
  473   
  474       private void writeColorSpace( PDColorSpace colorSpace ) throws IOException
  475       {
  476           COSName key = null;
  477           if( colorSpace instanceof PDDeviceGray ||
  478               colorSpace instanceof PDDeviceRGB ||
  479               colorSpace instanceof PDDeviceCMYK )
  480           {
  481               key = COSName.getPDFName( colorSpace.getName() );
  482           }
  483           else
  484           {
  485               COSDictionary colorSpaces =
  486                   (COSDictionary)resources.getCOSDictionary().getDictionaryObject(COSName.COLORSPACE);
  487               if( colorSpaces == null )
  488               {
  489                   colorSpaces = new COSDictionary();
  490                   resources.getCOSDictionary().setItem( COSName.COLORSPACE, colorSpaces );
  491               }
  492               key = colorSpaces.getKeyForValue( colorSpace.getCOSObject() );
  493   
  494               if( key == null )
  495               {
  496                   int counter = 0;
  497                   String csName = "CS";
  498                   while( colorSpaces.containsValue( csName + counter ) )
  499                   {
  500                       counter++;
  501                   }
  502                   key = COSName.getPDFName( csName + counter );
  503                   colorSpaces.setItem( key, colorSpace );
  504               }
  505           }
  506           key.writePDF( output );
  507           appendRawCommands( SPACE );
  508       }
  509   
  510       /**
  511        * Set the color components of current stroking colorspace.
  512        *
  513        * @param components The components to set for the current color.
  514        * @throws IOException If there is an error while writing to the stream.
  515        */
  516       public void setStrokingColor( float[] components ) throws IOException
  517       {
  518           for( int i=0; i< components.length; i++ )
  519           {
  520               appendRawCommands( formatDecimal.format( components[i] ) );
  521               appendRawCommands( SPACE );
  522           }
  523           if( currentStrokingColorSpace instanceof PDSeparation ||
  524               currentStrokingColorSpace instanceof PDPattern ||
  525               currentStrokingColorSpace instanceof PDDeviceN ||
  526               currentStrokingColorSpace instanceof PDICCBased )
  527           {
  528               appendRawCommands( SET_STROKING_COLOR_COMPLEX );
  529           }
  530           else
  531           {
  532               appendRawCommands( SET_STROKING_COLOR_SIMPLE );
  533           }
  534       }
  535   
  536       /**
  537        * Set the stroking color, specified as RGB.
  538        *
  539        * @param color The color to set.
  540        * @throws IOException If an IO error occurs while writing to the stream.
  541        */
  542       public void setStrokingColor( Color color ) throws IOException
  543       {
  544           ColorSpace colorSpace = color.getColorSpace();
  545           if( colorSpace.getType() == ColorSpace.TYPE_RGB )
  546           {
  547               setStrokingColor( color.getRed(), color.getGreen(), color.getBlue() );
  548           }
  549           else if( colorSpace.getType() == ColorSpace.TYPE_GRAY )
  550           {
  551               color.getColorComponents( colorComponents );
  552               setStrokingColor( colorComponents[0] );
  553           }
  554           else if( colorSpace.getType() == ColorSpace.TYPE_CMYK )
  555           {
  556               color.getColorComponents( colorComponents );
  557               setStrokingColor( colorComponents[0], colorComponents[2], colorComponents[2], colorComponents[3] );
  558           }
  559           else
  560           {
  561               throw new IOException( "Error: unknown colorspace:" + colorSpace );
  562           }
  563       }
  564   
  565       /**
  566        * Set the non stroking color, specified as RGB.
  567        *
  568        * @param color The color to set.
  569        * @throws IOException If an IO error occurs while writing to the stream.
  570        */
  571       public void setNonStrokingColor( Color color ) throws IOException
  572       {
  573           ColorSpace colorSpace = color.getColorSpace();
  574           if( colorSpace.getType() == ColorSpace.TYPE_RGB )
  575           {
  576               setNonStrokingColor( color.getRed(), color.getGreen(), color.getBlue() );
  577           }
  578           else if( colorSpace.getType() == ColorSpace.TYPE_GRAY )
  579           {
  580               color.getColorComponents( colorComponents );
  581               setNonStrokingColor( colorComponents[0] );
  582           }
  583           else if( colorSpace.getType() == ColorSpace.TYPE_CMYK )
  584           {
  585               color.getColorComponents( colorComponents );
  586               setNonStrokingColor( colorComponents[0], colorComponents[2], colorComponents[2], colorComponents[3] );
  587           }
  588           else
  589           {
  590               throw new IOException( "Error: unknown colorspace:" + colorSpace );
  591           }
  592       }
  593   
  594       /**
  595        * Set the stroking color, specified as RGB, 0-255.
  596        *
  597        * @param r The red value.
  598        * @param g The green value.
  599        * @param b The blue value.
  600        * @throws IOException If an IO error occurs while writing to the stream.
  601        */
  602       public void setStrokingColor( int r, int g, int b ) throws IOException
  603       {
  604           appendRawCommands( formatDecimal.format( r/255d ) );
  605           appendRawCommands( SPACE );
  606           appendRawCommands( formatDecimal.format( g/255d ) );
  607           appendRawCommands( SPACE );
  608           appendRawCommands( formatDecimal.format( b/255d ) );
  609           appendRawCommands( SPACE );
  610           appendRawCommands( RG_STROKING );
  611       }
  612   
  613       /**
  614        * Set the stroking color, specified as CMYK, 0-255.
  615        *
  616        * @param c The cyan value.
  617        * @param m The magenta value.
  618        * @param y The yellow value.
  619        * @param k The black value.
  620        * @throws IOException If an IO error occurs while writing to the stream.
  621        */
  622       public void setStrokingColor( int c, int m, int y, int k) throws IOException
  623       {
  624           appendRawCommands( formatDecimal.format( c/255d ) );
  625           appendRawCommands( SPACE );
  626           appendRawCommands( formatDecimal.format( m/255d ) );
  627           appendRawCommands( SPACE );
  628           appendRawCommands( formatDecimal.format( y/255d ) );
  629           appendRawCommands( SPACE );
  630           appendRawCommands( formatDecimal.format( k/255d ) );
  631           appendRawCommands( SPACE );
  632           appendRawCommands( K_STROKING );
  633       }
  634   
  635       /**
  636        * Set the stroking color, specified as CMYK, 0.0-1.0.
  637        *
  638        * @param c The cyan value.
  639        * @param m The magenta value.
  640        * @param y The yellow value.
  641        * @param k The black value.
  642        * @throws IOException If an IO error occurs while writing to the stream.
  643        */
  644       public void setStrokingColor( double c, double m, double y, double k) throws IOException
  645       {
  646           appendRawCommands( formatDecimal.format( c ) );
  647           appendRawCommands( SPACE );
  648           appendRawCommands( formatDecimal.format( m ) );
  649           appendRawCommands( SPACE );
  650           appendRawCommands( formatDecimal.format( y ) );
  651           appendRawCommands( SPACE );
  652           appendRawCommands( formatDecimal.format( k ) );
  653           appendRawCommands( SPACE );
  654           appendRawCommands( K_STROKING );
  655       }
  656   
  657       /**
  658        * Set the stroking color, specified as grayscale, 0-255.
  659        *
  660        * @param g The gray value.
  661        * @throws IOException If an IO error occurs while writing to the stream.
  662        */
  663       public void setStrokingColor( int g ) throws IOException
  664       {
  665           appendRawCommands( formatDecimal.format( g/255d ) );
  666           appendRawCommands( SPACE );
  667           appendRawCommands( G_STROKING );
  668       }
  669   
  670       /**
  671        * Set the stroking color, specified as Grayscale 0.0-1.0.
  672        *
  673        * @param g The gray value.
  674        * @throws IOException If an IO error occurs while writing to the stream.
  675        */
  676       public void setStrokingColor( double g ) throws IOException
  677       {
  678           appendRawCommands( formatDecimal.format( g ) );
  679           appendRawCommands( SPACE );
  680           appendRawCommands( G_STROKING );
  681       }
  682   
  683       /**
  684        * Set the color components of current non stroking colorspace.
  685        *
  686        * @param components The components to set for the current color.
  687        * @throws IOException If there is an error while writing to the stream.
  688        */
  689       public void setNonStrokingColor( float[] components ) throws IOException
  690       {
  691           for( int i=0; i< components.length; i++ )
  692           {
  693               appendRawCommands( formatDecimal.format( components[i] ) );
  694               appendRawCommands( SPACE );
  695           }
  696           if( currentNonStrokingColorSpace instanceof PDSeparation ||
  697               currentNonStrokingColorSpace instanceof PDPattern ||
  698               currentNonStrokingColorSpace instanceof PDDeviceN ||
  699               currentNonStrokingColorSpace instanceof PDICCBased )
  700           {
  701               appendRawCommands( SET_NON_STROKING_COLOR_COMPLEX );
  702           }
  703           else
  704           {
  705               appendRawCommands( SET_NON_STROKING_COLOR_SIMPLE );
  706           }
  707       }
  708   
  709       /**
  710        * Set the non stroking color, specified as RGB, 0-255.
  711        *
  712        * @param r The red value.
  713        * @param g The green value.
  714        * @param b The blue value.
  715        * @throws IOException If an IO error occurs while writing to the stream.
  716        */
  717       public void setNonStrokingColor( int r, int g, int b ) throws IOException
  718       {
  719           appendRawCommands( formatDecimal.format( r/255d ) );
  720           appendRawCommands( SPACE );
  721           appendRawCommands( formatDecimal.format( g/255d ) );
  722           appendRawCommands( SPACE );
  723           appendRawCommands( formatDecimal.format( b/255d ) );
  724           appendRawCommands( SPACE );
  725           appendRawCommands( RG_NON_STROKING );
  726       }
  727   
  728       /**
  729        * Set the non stroking color, specified as CMYK, 0-255.
  730        *
  731        * @param c The cyan value.
  732        * @param m The magenta value.
  733        * @param y The yellow value.
  734        * @param k The black value.
  735        * @throws IOException If an IO error occurs while writing to the stream.
  736        */
  737       public void setNonStrokingColor( int c, int m, int y, int k) throws IOException
  738       {
  739           appendRawCommands( formatDecimal.format( c/255d ) );
  740           appendRawCommands( SPACE );
  741           appendRawCommands( formatDecimal.format( m/255d ) );
  742           appendRawCommands( SPACE );
  743           appendRawCommands( formatDecimal.format( y/255d ) );
  744           appendRawCommands( SPACE );
  745           appendRawCommands( formatDecimal.format( k/255d ) );
  746           appendRawCommands( SPACE );
  747           appendRawCommands( K_NON_STROKING );
  748       }
  749   
  750       /**
  751        * Set the non stroking color, specified as CMYK, 0.0-1.0.
  752        *
  753        * @param c The cyan value.
  754        * @param m The magenta value.
  755        * @param y The yellow value.
  756        * @param k The black value.
  757        * @throws IOException If an IO error occurs while writing to the stream.
  758        */
  759       public void setNonStrokingColor( double c, double m, double y, double k) throws IOException
  760       {
  761           appendRawCommands( formatDecimal.format( c ) );
  762           appendRawCommands( SPACE );
  763           appendRawCommands( formatDecimal.format( m ) );
  764           appendRawCommands( SPACE );
  765           appendRawCommands( formatDecimal.format( y ) );
  766           appendRawCommands( SPACE );
  767           appendRawCommands( formatDecimal.format( k ) );
  768           appendRawCommands( SPACE );
  769           appendRawCommands( K_NON_STROKING );
  770       }
  771   
  772       /**
  773        * Set the non stroking color, specified as grayscale, 0-255.
  774        *
  775        * @param g The gray value.
  776        * @throws IOException If an IO error occurs while writing to the stream.
  777        */
  778       public void setNonStrokingColor( int g ) throws IOException
  779       {
  780           appendRawCommands( formatDecimal.format( g/255d ) );
  781           appendRawCommands( SPACE );
  782           appendRawCommands( G_NON_STROKING );
  783       }
  784   
  785       /**
  786        * Set the non stroking color, specified as Grayscale 0.0-1.0.
  787        *
  788        * @param g The gray value.
  789        * @throws IOException If an IO error occurs while writing to the stream.
  790        */
  791       public void setNonStrokingColor( double g ) throws IOException
  792       {
  793           appendRawCommands( formatDecimal.format( g ) );
  794           appendRawCommands( SPACE );
  795           appendRawCommands( G_NON_STROKING );
  796       }
  797   
  798       /**
  799        * Draw a rectangle on the page using the current non stroking color.
  800        *
  801        * @param x The lower left x coordinate.
  802        * @param y The lower left y coordinate.
  803        * @param width The width of the rectangle.
  804        * @param height The height of the rectangle.
  805        * @throws IOException If there is an error while drawing on the screen.
  806        */
  807       public void fillRect( float x, float y, float width, float height ) throws IOException
  808       {
  809           appendRawCommands( formatDecimal.format( x ) );
  810           appendRawCommands( SPACE );
  811           appendRawCommands( formatDecimal.format( y ) );
  812           appendRawCommands( SPACE );
  813           appendRawCommands( formatDecimal.format( width ) );
  814           appendRawCommands( SPACE );
  815           appendRawCommands( formatDecimal.format( height ) );
  816           appendRawCommands( SPACE );
  817           appendRawCommands( APPEND_RECTANGLE );
  818           appendRawCommands( FILL );
  819       }
  820   
  821       /**
  822        * Draw a line on the page using the current non stroking color and the current line width.
  823        *
  824        * @param xStart The start x coordinate.
  825        * @param yStart The start y coordinate.
  826        * @param xEnd The end x coordinate.
  827        * @param yEnd The end y coordinate.
  828        * @throws IOException If there is an error while drawing on the screen.
  829        */
  830       public void drawLine( float xStart, float yStart, float xEnd, float yEnd ) throws IOException
  831       {
  832           // moveTo
  833           appendRawCommands( formatDecimal.format( xStart) );
  834           appendRawCommands( SPACE );
  835           appendRawCommands( formatDecimal.format( yStart) );
  836           appendRawCommands( SPACE );
  837           appendRawCommands( MOVE_TO );
  838           // lineTo
  839           appendRawCommands( formatDecimal.format( xEnd ) );
  840           appendRawCommands( SPACE );
  841           appendRawCommands( formatDecimal.format( yEnd ) );
  842           appendRawCommands( SPACE );
  843           appendRawCommands( LINE_TO );
  844           // stroke
  845           appendRawCommands( STROKE );
  846   
  847       }
  848   
  849        /**
  850        * Set linewidth to the given value.
  851        *
  852        * @param lineWidth The width which is used for drwaing.
  853        * @throws IOException If there is an error while drawing on the screen.
  854        */
  855       public void setLineWidth(float lineWidth) throws IOException
  856       {
  857           appendRawCommands( formatDecimal.format( lineWidth ) );
  858           appendRawCommands( SPACE );
  859           appendRawCommands( LINE_WIDTH );
  860       }
  861       /**
  862        * This will append raw commands to the content stream.
  863        *
  864        * @param commands The commands to append to the stream.
  865        * @throws IOException If an error occurs while writing to the stream.
  866        */
  867       public void appendRawCommands( String commands ) throws IOException
  868       {
  869           appendRawCommands( commands.getBytes( "ISO-8859-1" ) );
  870       }
  871   
  872       /**
  873        * This will append raw commands to the content stream.
  874        *
  875        * @param commands The commands to append to the stream.
  876        * @throws IOException If an error occurs while writing to the stream.
  877        */
  878       public void appendRawCommands( byte[] commands ) throws IOException
  879       {
  880           output.write( commands );
  881       }
  882   
  883       /**
  884        * This will append raw commands to the content stream.
  885        *
  886        * @param data Append a raw byte to the stream.
  887        *
  888        * @throws IOException If an error occurs while writing to the stream.
  889        */
  890       public void appendRawCommands( int data ) throws IOException
  891       {
  892           output.write( data );
  893       }
  894   
  895       /**
  896        * Close the content stream.  This must be called when you are done with this
  897        * object.
  898        * @throws IOException If the underlying stream has a problem being written to.
  899        */
  900       public void close() throws IOException
  901       {
  902           output.close();
  903       }
  904   }

Home » pdfbox-1.1.0-src » org.apache.pdfbox.pdmodel.edit » [javadoc | source]