You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-dev@xmlgraphics.apache.org by vh...@apache.org on 2001/03/07 02:20:23 UTC

cvs commit: xml-batik/sources/org/apache/batik/transcoder/print PrintTranscoder.java

vhardy      01/03/06 17:20:22

  Modified:    sources/org/apache/batik/transcoder AbstractTranscoder.java
                        XMLAbstractTranscoder.java
  Added:       sources/org/apache/batik/transcoder/print
                        PrintTranscoder.java
  Log:
  Added PrintTranscoder. Moved common transcoding keys to AbstractTranscoder.
  
  Revision  Changes    Path
  1.2       +227 -3    xml-batik/sources/org/apache/batik/transcoder/AbstractTranscoder.java
  
  Index: AbstractTranscoder.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/transcoder/AbstractTranscoder.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AbstractTranscoder.java	2001/01/09 10:51:43	1.1
  +++ AbstractTranscoder.java	2001/03/07 01:20:20	1.2
  @@ -8,19 +8,243 @@
   
   package org.apache.batik.transcoder;
   
  +import java.awt.geom.Rectangle2D;
  +import java.awt.Paint;
  +
   /**
    * This class can be the base class of a transcoder which may support
    * transcoding hints and/or error handler.
    *
    * @author <a href="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
  - * @version $Id: AbstractTranscoder.java,v 1.1 2001/01/09 10:51:43 tkormann Exp $
  + * @version $Id: AbstractTranscoder.java,v 1.2 2001/03/07 01:20:20 vhardy Exp $
    */
   public abstract class AbstractTranscoder extends TranscoderSupport
  -        implements Transcoder {
  -
  +    implements Transcoder {
  +    
       /**
        * Constructs a new <tt>AbstractTranscoder</tt>.
        */
       protected AbstractTranscoder() {}
   
  +    // --------------------------------------------------------------------
  +    // Keys definition
  +    // --------------------------------------------------------------------
  +
  +    /**
  +     * The image width key.
  +     * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
  +     * <TD VALIGN="TOP">KEY_WIDTH</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
  +     * <TD VALIGN="TOP">Float</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
  +     * <TD VALIGN="TOP">The width of the top most svg element</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
  +     * <TD VALIGN="TOP">No</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
  +     * <TD VALIGN="TOP">Specify the width of the image to create.</TD></TR>
  +     * </TABLE> */
  +    public static final TranscodingHints.Key KEY_WIDTH
  +        = new LengthKey(0);
  +    public static final String KEY_WIDTH_STR = "width";
  +
  +    /**
  +     * The image height key.
  +     * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
  +     * <TD VALIGN="TOP">KEY_HEIGHT</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
  +     * <TD VALIGN="TOP">Float</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
  +     * <TD VALIGN="TOP">The height of the top most svg element</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
  +     * <TD VALIGN="TOP">No</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
  +     * <TD VALIGN="TOP">Specify the height of the image to create.</TD></TR>
  +     * </TABLE> */
  +    public static final TranscodingHints.Key KEY_HEIGHT
  +        = new LengthKey(1);
  +    public static final String KEY_HEIGHT_STR = "height";
  +
  +    /**
  +     * The area of interest key.
  +     * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
  +     * <TD VALIGN="TOP">KEY_AOI</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
  +     * <TD VALIGN="TOP">Rectangle2D</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
  +     * <TD VALIGN="TOP">The document's size</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
  +     * <TD VALIGN="TOP">No</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
  +     * <TD VALIGN="TOP">Specify the area of interest to render. The
  +     * rectangle coordinates must be specified in pixels and in the
  +     * document coordinates system.</TD></TR>
  +     * </TABLE>
  +     */
  +    public static final TranscodingHints.Key KEY_AOI
  +        = new Rectangle2DKey(0);
  +    public static final String KEY_AOI_STR = "aoi";
  +
  +    /**
  +     * The language key.
  +     * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
  +     * <TD VALIGN="TOP">KEY_LANGUAGE</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
  +     * <TD VALIGN="TOP">String</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
  +     * <TD VALIGN="TOP">"en"</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
  +     * <TD VALIGN="TOP">No</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
  +     * <TD VALIGN="TOP">Specify the preferred language of the document.
  +     * </TD></TR>
  +     * </TABLE>
  +     */
  +    public static final TranscodingHints.Key KEY_LANGUAGE
  +        = new StringKey(0);
  +    public static final String KEY_LANGUAGE_STR = "language";
  +
  +    /**
  +     * The user stylesheet URI key.
  +     * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
  +     * <TD VALIGN="TOP">KEY_USER_STYLESHEET_URI</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
  +     * <TD VALIGN="TOP">String</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
  +     * <TD VALIGN="TOP">null</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
  +     * <TD VALIGN="TOP">No</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
  +     * <TD VALIGN="TOP">Specify the user style sheet.</TD></TR>
  +     * </TABLE>
  +     */
  +    public static final TranscodingHints.Key KEY_USER_STYLESHEET_URI
  +        = new StringKey(1);
  +    public static final String KEY_USER_STYLESHEET_URI_STR = "userStylesheet";
  +
  +    /**
  +     * The pixel to millimeter conversion factor key.
  +     * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
  +     * <TD VALIGN="TOP">KEY_PIXEL_TO_MM</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
  +     * <TD VALIGN="TOP">Float</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
  +     * <TD VALIGN="TOP">0.33</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
  +     * <TD VALIGN="TOP">No</TD></TR>
  +     * <TR>
  +     * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
  +     * <TD VALIGN="TOP">Specify the pixel to millimeter conversion factor.
  +     * </TD></TR>
  +     * </TABLE>
  +     */
  +    public static final TranscodingHints.Key KEY_PIXEL_TO_MM
  +        = new FloatKey(0);
  +    public static final String KEY_PIXEL_TO_MM_STR = "pixelToMm";
  +
  +    /**
  +     * A transcoding Key represented as a string.
  +     */
  +    public static class StringKey extends TranscodingHints.Key {
  +        public StringKey(int privatekey) {
  +            super(privatekey);
  +        }
  +        public boolean isCompatibleValue(Object v) {
  +            return (v instanceof String);
  +        }
  +    }
  +
  +    /**
  +     * A transcoding Key represented as a boolean.
  +     */
  +    public static class BooleanKey extends TranscodingHints.Key {
  +        public BooleanKey(int privatekey) {
  +            super(privatekey);
  +        }
  +        public boolean isCompatibleValue(Object v) {
  +            return (v != null && v instanceof Boolean);
  +        }
  +    }
  +
  +    /**
  +     * A transcoding Key represented as a float.
  +     */
  +    public static class FloatKey extends TranscodingHints.Key {
  +        public FloatKey(int privatekey) {
  +            super(privatekey);
  +        }
  +        public boolean isCompatibleValue(Object v) {
  +            return (v instanceof Float);
  +        }
  +    }
  +
  +    /**
  +     * A transcoding Key represented as a length.
  +     */
  +    public static class LengthKey extends TranscodingHints.Key {
  +        public LengthKey(int privatekey) {
  +            super(privatekey);
  +        }
  +        public boolean isCompatibleValue(Object v) {
  +            return (v instanceof Float && ((Float)v).floatValue() > 0);
  +        }
  +    }
  +
  +    /**
  +     * A transcoding Key represented as a background paint.
  +     */
  +    public static class PaintKey extends TranscodingHints.Key {
  +        public PaintKey(int privatekey) {
  +            super(privatekey);
  +        }
  +        public boolean isCompatibleValue(Object v) {
  +            return (v instanceof Paint);
  +        }
  +    }
  +
  +    /**
  +     * A transcoding Key represented as a rectangle.
  +     */
  +    public static class Rectangle2DKey extends TranscodingHints.Key {
  +        public Rectangle2DKey(int privatekey) {
  +            super(privatekey);
  +        }
  +        public boolean isCompatibleValue(Object v) {
  +            return (v instanceof Rectangle2D);
  +        }
  +    }
   }
  
  
  
  1.6       +9 -18     xml-batik/sources/org/apache/batik/transcoder/XMLAbstractTranscoder.java
  
  Index: XMLAbstractTranscoder.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/transcoder/XMLAbstractTranscoder.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- XMLAbstractTranscoder.java	2001/01/29 15:36:46	1.5
  +++ XMLAbstractTranscoder.java	2001/03/07 01:20:21	1.6
  @@ -37,7 +37,7 @@
    * </ul>
    *
    * @author <a href="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
  - * @version $Id: XMLAbstractTranscoder.java,v 1.5 2001/01/29 15:36:46 tkormann Exp $
  + * @version $Id: XMLAbstractTranscoder.java,v 1.6 2001/03/07 01:20:21 vhardy Exp $
    */
   public abstract class XMLAbstractTranscoder extends AbstractTranscoder {
   
  @@ -106,6 +106,7 @@
                                                   input.getURI(),
                                                   input.getReader());
                   } else if (input.getURI() != null) {
  +                    System.out.println("Creating Document from URI...");
                       document = f.createDocument(namespaceURI,
                                                   documentElement,
                                                   input.getURI());
  @@ -113,6 +114,7 @@
               } catch (DOMException ex) {
                   handler.fatalError(new TranscoderException(ex));
               } catch (IOException ex) {
  +                ex.printStackTrace();
                   handler.fatalError(new TranscoderException(ex));
               }
           }
  @@ -177,7 +179,8 @@
        * </TABLE>
        */
       public static final TranscodingHints.Key KEY_XML_PARSER_CLASSNAME
  -        = new StringKey(0);
  +        = new StringKey(10);
  +    public static final String KEY_XML_PARSER_CLASSNAME_STR = "xmlParserClassName";
   
       /**
        * Document element key.
  @@ -201,7 +204,7 @@
        * </TABLE>
        */
       public static final TranscodingHints.Key KEY_DOCUMENT_ELEMENT
  -        = new StringKey(2);
  +        = new StringKey(12);
   
       /**
        * Document element namespace URI key.
  @@ -226,7 +229,7 @@
        * </TABLE>
        */
       public static final TranscodingHints.Key KEY_DOCUMENT_ELEMENT_NAMESPACE_URI
  -        = new StringKey(3);
  +        = new StringKey(13);
   
       /**
        * DOM Implementation key.
  @@ -250,24 +253,12 @@
        * </TABLE>
        */
       public static final TranscodingHints.Key KEY_DOM_IMPLEMENTATION
  -        = new DOMImplKey(0);
  +        = new DOMImplKey(14);
   
       /**
  -     * A transcoding Key represented as a string.
  -     */
  -    private static class StringKey extends TranscodingHints.Key {
  -        public StringKey(int privatekey) {
  -            super(privatekey);
  -        }
  -        public boolean isCompatibleValue(Object v) {
  -            return (v instanceof String);
  -        }
  -    }
  -
  -    /**
        * A transcoding Key represented as a DOMImplementation.
        */
  -    private static class DOMImplKey extends TranscodingHints.Key {
  +    public static class DOMImplKey extends TranscodingHints.Key {
           public DOMImplKey(int privatekey) {
               super(privatekey);
           }
  
  
  
  1.1                  xml-batik/sources/org/apache/batik/transcoder/print/PrintTranscoder.java
  
  Index: PrintTranscoder.java
  ===================================================================
  /*****************************************************************************
   * Copyright (C) The Apache Software Foundation. All rights reserved.        *
   * ------------------------------------------------------------------------- *
   * This software is published under the terms of the Apache Software License *
   * version 1.1, a copy of which has been included with this distribution in  *
   * the LICENSE file.                                                         *
   *****************************************************************************/
  
  package org.apache.batik.transcoder.print;
  
  import java.awt.Cursor;
  import java.awt.Dimension;
  import java.awt.Graphics;
  import java.awt.Graphics2D;
  import java.awt.Point;
  import java.awt.RenderingHints;
  import java.awt.Shape;
  import java.awt.font.FontRenderContext;
  import java.awt.geom.AffineTransform;
  import java.awt.geom.Dimension2D;
  import java.awt.geom.Rectangle2D;
  
  import java.awt.image.BufferedImage;
  import java.awt.image.DataBufferInt;
  import java.awt.image.SinglePixelPackedSampleModel;
  import java.awt.print.Printable;
  import java.awt.print.PageFormat;
  import java.awt.print.Paper;
  import java.awt.print.PrinterJob;
  import java.awt.print.PrinterException;
  
  import java.io.File;
  import java.io.IOException;
  import java.io.OutputStream;
  
  import java.util.StringTokenizer;
  import java.util.Vector;
  
  import org.apache.batik.dom.svg.DefaultSVGContext;
  import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
  import org.apache.batik.dom.svg.SVGDOMImplementation;
  import org.apache.batik.dom.svg.SVGOMDocument;
  import org.apache.batik.dom.util.DocumentFactory;
  
  import org.apache.batik.gvt.GraphicsNodeRenderContext;
  import org.apache.batik.gvt.GraphicsNode;
  import org.apache.batik.gvt.TextPainter;
  
  import org.apache.batik.gvt.filter.GraphicsNodeRableFactory;
  import org.apache.batik.gvt.filter.ConcreteGraphicsNodeRableFactory;
  import org.apache.batik.gvt.renderer.StrokingTextPainter;
  
  import org.apache.batik.bridge.BridgeContext;
  import org.apache.batik.bridge.GVTBuilder;
  import org.apache.batik.bridge.ConcreteGVTBuilder;
  import org.apache.batik.bridge.UserAgent;
  import org.apache.batik.bridge.SVGUtilities;
  
  import org.apache.batik.gvt.event.EventDispatcher;
  
  import org.apache.batik.transcoder.Transcoder;
  import org.apache.batik.transcoder.TranscoderException;
  import org.apache.batik.transcoder.TranscoderInput;
  import org.apache.batik.transcoder.TranscoderOutput;
  import org.apache.batik.transcoder.TranscodingHints;
  import org.apache.batik.transcoder.XMLAbstractTranscoder;
  
  import org.apache.batik.util.SVGConstants;
  
  import org.w3c.dom.DOMException;
  import org.w3c.dom.DOMImplementation;
  import org.w3c.dom.Document;
  import org.w3c.dom.svg.SVGAElement;
  import org.w3c.dom.svg.SVGDocument;
  import org.w3c.dom.svg.SVGSVGElement;
  
  /**
   * This class is a <tt>Transcoder</tt> that prints SVG images.
   * This class works as follows: any-time the transcode method
   * is invoked, the corresponding input is cached and nothing
   * else happens. <br />
   * However, the <tt>PrintTranscoder</tt> is also a Printable. If used
   * in a print operation, it will print each of the input 
   * it cached, one input per page.
   * <br />
   * The <tt>PrintTranscoder</tt> uses several different hints that
   * guide its printing:<br />
   * <ul>
   *   <li><tt>KEY_LANGUAGE, KEY_USER_STYLESHEET_URI, KEY_PIXEL_TO_MM,
   *       KEY_XML_PARSER_CLASSNAME</tt> can be used to set the defaults for 
   *       the various SVG properties.</li>
   *   <li><tt>KEY_PAGE_WIDTH, KEY_PAGE_HEIGHT, KEY_MARGIN_TOP, KEY_MARGIN_BOTTOM,
   *       KEY_MARGIN_LEFT, KEY_MARGIN_RIGHT</tt> and <tt>KEY_PAGE_ORIENTATION</tt>
   *       can be used to specify the printing page characteristics.</li>
   *   <li><tt>KEY_WIDTH, KEY_HEIGHT</tt> can be used to specify how to scale the 
   *       SVG image</li>
   *   <li><tt>KEY_SCALE_TO_PAGE</tt> can be used to specify whether or not the 
   *       SVG image should be scaled uniformly to fit into the printed page or
   *       if it should just be centered into the printed page.</li>
   * </ul>
   *
   * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
   * @version $Id: PrintTranscoder.java,v 1.1 2001/03/07 01:20:22 vhardy Exp $
   */
  public class PrintTranscoder extends XMLAbstractTranscoder  
      implements Printable{
      /**
       * Set of inputs this transcoder has been requested to 
       * transcode so far
       */
      private Vector inputs = new Vector();
  
      /**
       * Currently printing set of pages. This vector is 
       * created as a clone of inputs when the first page is printed.
       */
      private Vector printedInputs = null;
  
      /**
       * Current GVT Tree, i.e., the GVT tree representing the page
       * being printed currently.
       */
      private GraphicsNode root;
  
      /**
       * Index of the page corresponding to root
       */
      private int curIndex = -1;
  
      /**
       * Current area of interest.
       */
      private Rectangle2D curAOI;
  
      /**
       * Transform needed to render the current area of interest
       */
      private AffineTransform curTxf;
  
      /**
       * GraphicsNodeRenderContext used by this transcoder to render
       * the GVT trees.
       */
      private GraphicsNodeRenderContext nodeRenderContext;
  
      /**
       * UserAgent. Configuration comes from hints
       */
      private UserAgent userAgent = new PrintTranscoderUserAgent();
  
      /**
       * Creates a <tt>DocumentFactory</tt> that is used to create an SVG DOM
       * tree. The specified DOM Implementation is ignored and the Batik
       * SVG DOM Implementation is automatically used.
       *
       * @param domImpl the DOM Implementation (not used)
       * @param parserClassname the XML parser classname
       */
      protected DocumentFactory createDocumentFactory(DOMImplementation domImpl,
                                                      String parserClassname) {
          return new SAXSVGDocumentFactory(parserClassname);
      }
  
      /**
       * Constructs a new transcoder that prints images.
       */
      public PrintTranscoder() { 
          hints.put(KEY_DOCUMENT_ELEMENT_NAMESPACE_URI,
                    SVGConstants.SVG_NAMESPACE_URI);
          hints.put(KEY_DOCUMENT_ELEMENT,
                    SVGConstants.SVG_SVG_TAG);
          hints.put(KEY_DOM_IMPLEMENTATION,
                    SVGDOMImplementation.getDOMImplementation());
      }
  
      public void transcode(TranscoderInput in,
                             TranscoderOutput out){
          if(in != null){
              inputs.addElement(in);
          }
      }
  
      /**
       * Convenience method
       */
      public void print() throws PrinterException{
          //
          // Now, request the transcoder to actually perform the 
          // printing job.
          //
          PrinterJob printerJob =
              PrinterJob.getPrinterJob();
  
          PageFormat pageFormat =
              printerJob.defaultPage();
  
          //
          // Set the page parameters from the hints
          //
          Paper paper = pageFormat.getPaper();
          
          Float pageWidth = (Float)hints.get(KEY_PAGE_WIDTH);
          Float pageHeight = (Float)hints.get(KEY_PAGE_HEIGHT);
          if(pageWidth != null){
              paper.setSize(pageWidth.floatValue(),
                            paper.getHeight());
          }
          if(pageHeight != null){
              paper.setSize(paper.getWidth(),
                            pageHeight.floatValue());
          }
  
          float x=0, y=0, width=(float)paper.getWidth(), height=(float)paper.getHeight();
          
          Float leftMargin = (Float)hints.get(KEY_MARGIN_LEFT);
          Float topMargin = (Float)hints.get(KEY_MARGIN_TOP);
          Float rightMargin = (Float)hints.get(KEY_MARGIN_RIGHT);
          Float bottomMargin = (Float)hints.get(KEY_MARGIN_BOTTOM);
  
          if(leftMargin != null){
              x = leftMargin.floatValue();
              width -= leftMargin.floatValue();
          }
          if(topMargin != null){
              y = topMargin.floatValue();
              height -= topMargin.floatValue();
          }
          if(rightMargin != null){
              width -= rightMargin.floatValue();
          }
          if(bottomMargin != null){
              height -= bottomMargin.floatValue();
          }
  
          paper.setImageableArea(x, y, width, height);
  
          String pageOrientation = (String)hints.get(KEY_PAGE_ORIENTATION);
          if(VALUE_PAGE_ORIENTATION_PORTRAIT.equalsIgnoreCase(pageOrientation)){
              pageFormat.setOrientation(pageFormat.PORTRAIT);
          }
          else if(VALUE_PAGE_ORIENTATION_LANDSCAPE.equalsIgnoreCase(pageOrientation)){
              pageFormat.setOrientation(pageFormat.LANDSCAPE);
          }
          else if(VALUE_PAGE_ORIENTATION_REVERSE_LANDSCAPE.equalsIgnoreCase(pageOrientation)){
              pageFormat.setOrientation(pageFormat.REVERSE_LANDSCAPE);
          }
  
          pageFormat.setPaper(paper);
          pageFormat = printerJob.validatePage(pageFormat);
          
          // Print on the default printer: there is no way in
          // the Java API to set the printer by program (without
          // a GUI).
          printerJob.setPrintable(this, pageFormat);
          printerJob.print();
  
      }
  
      /**
       * Printable implementation
       */
      public int print(Graphics _g, PageFormat pageFormat, int pageIndex){
          //
          // On the first page, take a snapshot of the vector of 
          // TranscodeInputs.
          //
          if(pageIndex == 0){
              printedInputs = (Vector)inputs.clone();
          }
  
          //
          // If we have already printed each page, return
          //
          if(pageIndex >= printedInputs.size()){
              curIndex = -1;
              System.out.println("Done");
              return NO_SUCH_PAGE;
          }
  
          //
          // Load a new document now if we are printing a new page
          //
          if(curIndex != pageIndex){
              // The following call will invoke this class' transcode
              // method which takes a document as an input. That method
              // builds the GVT root tree.{
              try{
                  super.transcode((TranscoderInput)printedInputs.elementAt(pageIndex),
                                  null);
                  curIndex = pageIndex;
              }catch(TranscoderException e){
                  drawError(_g, e);
                  return PAGE_EXISTS;
              }
          }
          
          // Cast to Graphics2D to access Java 2D features
          Graphics2D g = (Graphics2D)_g;
          g.addRenderingHints(nodeRenderContext.getRenderingHints());
          
          
          //
          // Compute transform so that the SVG document fits on one page
          //
          AffineTransform t = g.getTransform();
          Shape clip = g.getClip();
  
          Rectangle2D bounds = curAOI;
          
          double scaleX = pageFormat.getImageableWidth() / bounds.getWidth();
          double scaleY = pageFormat.getImageableHeight() / bounds.getHeight();
          double scale = scaleX < scaleY ? scaleX : scaleY;
          
          // Check hint to know if scaling is really needed
          Boolean scaleToPage = (Boolean)hints.get(KEY_SCALE_TO_PAGE);
          if(scaleToPage != null && !scaleToPage.booleanValue()){
              scale = 1;
          }
  
          double xMargin = (pageFormat.getImageableWidth() - bounds.getWidth()*scale)/2;
          double yMargin = (pageFormat.getImageableHeight() - bounds.getHeight()*scale)/2;
          g.translate(pageFormat.getImageableX() + xMargin, 
                      pageFormat.getImageableY() + yMargin);
          g.scale(scale, scale);
  
  
          //
          // Append transform to selected area
          //
          g.transform(curTxf);
          
          g.clip(curAOI);
  
          //
          // Delegate rendering to painter
          //
          try{
              root.paint(g, nodeRenderContext);
          }catch(Exception e){
              g.setTransform(t);
              g.setClip(clip);
              drawError(_g, e);
          }
          
          //
          // Restore transform and clip
          //
          g.setTransform(t);
          g.setClip(clip);
  
          // g.setPaint(Color.black);
          // g.drawString(uris[pageIndex], 30, 30);
          
          
          //
          // Return status indicated that we did paint a page
          //
          return PAGE_EXISTS;
      }
  
      /**
       * Prints an error on the output page
       */
      private void drawError(Graphics g, Exception e){
          // Do nothing now. 
      }
  
      /**
       * Transcodes the specified Document as an image in the specified output.
       * @param document the document to transcode
       * @param output the ouput where to transcode
       * @exception TranscoderException if an error occured while transcoding
       */
      protected void transcode(Document document, TranscoderOutput output)
              throws TranscoderException {
          // We can only handle SVG documents.
          if (!(document instanceof SVGOMDocument)) {
              // <!> TO BE FIXED WHEN WE DO ERROR HANDLING PROPERLY
              throw new TranscoderException("");
          }
  
          SVGDocument svgDoc = (SVGDocument)document;
          SVGSVGElement root = svgDoc.getRootElement();
  
          // 
          // Initialize the SVG document with the appropriate context
          //
          String parserClassname = (String)hints.get(KEY_XML_PARSER_CLASSNAME);
          DefaultSVGContext svgCtx = new DefaultSVGContext();
          svgCtx.setPixelToMM(userAgent.getPixelToMM());
          ((SVGOMDocument)document).setSVGContext(svgCtx);
  
          //
          // Get the 'width' and 'height' attributes of the SVG document
          //
          float docWidth = (int)root.getWidth().getBaseVal().getValue();
          float docHeight = (int)root.getHeight().getBaseVal().getValue();
  
          //
          // Compute the image's width and height according the hints
          //
          float imgWidth = -1;
          if (hints.containsKey(KEY_WIDTH)) {
              imgWidth = ((Float)hints.get(KEY_WIDTH)).floatValue();
          }
          float imgHeight = -1;
          if (hints.containsKey(KEY_HEIGHT)) {
              imgHeight = ((Float)hints.get(KEY_HEIGHT)).floatValue();
          }
          float width, height;
          if (imgWidth > 0 && imgHeight > 0) {
              width = imgWidth;
              height = imgHeight;
          } else if (imgHeight > 0) {
              width = (docWidth * imgHeight) / docHeight;
              height = imgHeight;
          } else if (imgWidth > 0) {
              width = imgWidth;
              height = (docHeight * imgWidth) / docWidth;
          } else {
              width = docWidth;
              height = docHeight;
          }
  
          //
          // Compute the preserveAspectRatio matrix
          //
          AffineTransform Px =
              SVGUtilities.getPreserveAspectRatioTransform(root, width, height);
          if (Px.isIdentity() && (width != docWidth || height != docHeight)) {
              // The document has no viewBox, we need to resize it by hand.
              // we want to keep the document size ratio
              float d = Math.max(docWidth, docHeight);
              float dd = Math.max(width, height);
              float scale = dd/d;
              Px = AffineTransform.getScaleInstance(scale, scale);
          }
  
          //
          // Take the AOI into account if any
          //
          if (hints.containsKey(KEY_AOI)) {
              Rectangle2D aoi = (Rectangle2D)hints.get(KEY_AOI);
              // transform the AOI into the image's coordinate system
              aoi = Px.createTransformedShape(aoi).getBounds2D();
              AffineTransform Mx = new AffineTransform();
              double sx = width / aoi.getWidth();
              double sy = height / aoi.getHeight();
              double tx = -aoi.getX();
              double ty = -aoi.getY();
              Mx.translate(tx, ty);
              // take the AOI transformation matrix into account
              // we apply first the preserveAspectRatio matrix
              Px.preConcatenate(Mx);
  
              curAOI = aoi;
          }
          else{
              curAOI = new Rectangle2D.Float(0, 0, width, height);
          }
  
          curTxf = Px;
  
          //
          // Build the GVT tree
          //
          GVTBuilder builder = new ConcreteGVTBuilder();
          GraphicsNodeRenderContext rc = getRenderContext();
          BridgeContext ctx = new BridgeContext(userAgent, rc);
          this.root = builder.build(ctx, svgDoc);
  
      }
  
      /**
       * Builds a GraphicsNodeRenderContext
       */
      public GraphicsNodeRenderContext getRenderContext() {
          if (nodeRenderContext == null) {
              RenderingHints hints = new RenderingHints(null);
              hints.put(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
  
              hints.put(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
  
              FontRenderContext fontRenderContext =
                  new FontRenderContext(new AffineTransform(), true, true);
  
              TextPainter textPainter = new StrokingTextPainter();
  
              GraphicsNodeRableFactory gnrFactory =
                  new ConcreteGraphicsNodeRableFactory();
  
              nodeRenderContext =
                  new GraphicsNodeRenderContext(new AffineTransform(),
                                            null,
                                            hints,
                                            fontRenderContext,
                                            textPainter,
                                            gnrFactory);
              }
  
          return nodeRenderContext;
      }
  
      /**
       * A user agent implementation for <tt>PrintTranscoder</tt>.
       */
      class PrintTranscoderUserAgent implements UserAgent {
  
          /**
           * Returns the default size of this user agent (400x400).
           */
          public Dimension2D getViewportSize() {
              return new Dimension(400, 400);
          }
  
          /**
           * Displays the specified error message using the <tt>ErrorHandler</tt>.
           */
          public void displayError(String message) {
              try {
                  handler.error(new TranscoderException(message));
              } catch (TranscoderException ex) {
                  throw new RuntimeException();
              }
          }
  
          /**
           * Displays the specified error using the <tt>ErrorHandler</tt>.
           */
          public void displayError(Exception e) {
              try {
                  handler.error(new TranscoderException(e));
              } catch (TranscoderException ex) {
                  throw new RuntimeException();
              }
          }
  
          /**
           * Displays the specified message using the <tt>ErrorHandler</tt>.
           */
          public void displayMessage(String message) {
              try {
                  handler.warning(new TranscoderException(message));
              } catch (TranscoderException ex) {
                  throw new RuntimeException();
              }
          }
  
          /**
           * Returns the pixel to millimeter conversion factor specified in the
           * <tt>TranscodingHints</tt> or 0.3528 if any.
           */
          public float getPixelToMM() {
              if (hints.containsKey(KEY_PIXEL_TO_MM)) {
                  return ((Float)hints.get(KEY_PIXEL_TO_MM)).floatValue();
              } else {
                  // return 0.3528f; // 72 dpi
                  return 0.26458333333333333333333333333333f; // 96dpi
              }
          }
  
          /**
           * Returns the user language specified in the
           * <tt>TranscodingHints</tt> or "en" (english) if any.
           */
          public String getLanguages() {
              if (hints.containsKey(KEY_LANGUAGE)) {
                  return (String)hints.get(KEY_LANGUAGE);
              } else {
                  return "en";
              }
          }
  
          /**
           * Returns the user stylesheet specified in the
           * <tt>TranscodingHints</tt> or null if any.
           */
          public String getUserStyleSheetURI() {
              return (String)hints.get(KEY_USER_STYLESHEET_URI);
          }
  
          /**
           * Returns the XML parser to use from the TranscodingHints.
           */
          public String getXMLParserClassName() {
              return (String)hints.get(KEY_XML_PARSER_CLASSNAME);
          }
  
          /**
           * Unsupported operation.
           */
          public EventDispatcher getEventDispatcher() {
              return null;
          }
  
          /**
           * Unsupported operation.
           */
          public void openLink(SVGAElement elt) { }
  
          /**
           * Unsupported operation.
           */
          public void setSVGCursor(Cursor cursor) { }
  
          /**
           * Unsupported operation.
           */
          public void runThread(Thread t) { }
  
          /**
           * Unsupported operation.
           */
          public AffineTransform getTransform() {
              return null;
          }
  
          /**
           * Unsupported operation.
           */
          public Point getClientAreaLocationOnScreen() {
              return new Point();
          }
      }
  
      /**
       * The pageWidth key.
       * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
       * <TD VALIGN="TOP">KEY_PAGE_WIDTH</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
       * <TD VALIGN="TOP">Length</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
       * <TD VALIGN="TOP">None</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
       * <TD VALIGN="TOP">No</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
       * <TD VALIGN="TOP">The width of the print page</TD></TR>
       * </TABLE> */
      public static final TranscodingHints.Key KEY_PAGE_WIDTH
          = new LengthKey(21);
      public static final String KEY_PAGE_WIDTH_STR = "pageWidth";
  
      /**
       * The pageHeight key.
       * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
       * <TD VALIGN="TOP">KEY_PAGE_HEIGHT</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
       * <TD VALIGN="TOP">Length</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
       * <TD VALIGN="TOP">None</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
       * <TD VALIGN="TOP">No</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
       * <TD VALIGN="TOP">The height of the print page</TD></TR>
       * </TABLE> */
      public static final TranscodingHints.Key KEY_PAGE_HEIGHT
          = new LengthKey(22);
      public static final String KEY_PAGE_HEIGHT_STR = "pageHeight";
  
      /**
       * The marginTop key.
       * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
       * <TD VALIGN="TOP">KEY_MARGIN_TOP</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
       * <TD VALIGN="TOP">Length</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
       * <TD VALIGN="TOP">None</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
       * <TD VALIGN="TOP">No</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
       * <TD VALIGN="TOP">The print page top margin</TD></TR>
       * </TABLE> */
      public static final TranscodingHints.Key KEY_MARGIN_TOP
          = new LengthKey(23);
      public static final String KEY_MARGIN_TOP_STR = "marginTop";
  
  
      /**
       * The marginRight key.
       * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
       * <TD VALIGN="TOP">KEY_MARGIN_RIGHT</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
       * <TD VALIGN="TOP">Length</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
       * <TD VALIGN="TOP">None</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
       * <TD VALIGN="TOP">No</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
       * <TD VALIGN="TOP">The print page right margin</TD></TR>
       * </TABLE> */
      public static final TranscodingHints.Key KEY_MARGIN_RIGHT
          = new LengthKey(24);
      public static final String KEY_MARGIN_RIGHT_STR = "marginRight";
  
      /**
       * The marginBottom key.
       * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
       * <TD VALIGN="TOP">KEY_MARGIN_BOTTOM</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
       * <TD VALIGN="TOP">Length</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
       * <TD VALIGN="TOP">None</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
       * <TD VALIGN="TOP">No</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
       * <TD VALIGN="TOP">The print page bottom margin</TD></TR>
       * </TABLE> */
      public static final TranscodingHints.Key KEY_MARGIN_BOTTOM
          = new LengthKey(25);
      public static final String KEY_MARGIN_BOTTOM_STR = "marginBottom";
  
      /**
       * The marginLeft key.
       * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
       * <TD VALIGN="TOP">KEY_MARGIN_LEFT</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
       * <TD VALIGN="TOP">Length</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
       * <TD VALIGN="TOP">None</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
       * <TD VALIGN="TOP">No</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
       * <TD VALIGN="TOP">The print page left margin</TD></TR>
       * </TABLE> */
      public static final TranscodingHints.Key KEY_MARGIN_LEFT
          = new LengthKey(26);
      public static final String KEY_MARGIN_LEFT_STR = "marginLeft";
  
      /**
       * The pageOrientation key.
       * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
       * <TD VALIGN="TOP">KEY_PAGE_ORIENTATION</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
       * <TD VALIGN="TOP">String</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
       * <TD VALIGN="TOP">VALUE_PAGE_ORIENTATION_PORTRAIT</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
       * <TD VALIGN="TOP">No</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
       * <TD VALIGN="TOP">The print page's orientation</TD></TR>
       * </TABLE> */
      public static final TranscodingHints.Key KEY_PAGE_ORIENTATION
          = new StringKey(27);
      public static final String KEY_PAGE_ORIENTATION_STR         = "pageOrientation";
      public static final String VALUE_PAGE_ORIENTATION_PORTRAIT  = "portrait";
      public static final String VALUE_PAGE_ORIENTATION_LANDSCAPE = "landscape";
      public static final String VALUE_PAGE_ORIENTATION_REVERSE_LANDSCAPE = "reverseLandscape";
  
      /**
       * The scaleToPage key.
       * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
       * <TD VALIGN="TOP">KEY_SCALE_TO_PAGE</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
       * <TD VALIGN="TOP">Boolean</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
       * <TD VALIGN="TOP">true</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
       * <TD VALIGN="TOP">No</TD></TR>
       * <TR>
       * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
       * <TD VALIGN="TOP">Specifies whether or not the SVG images are scaled to
       *                  fit into the printed page</TD></TR>
       * </TABLE> */
      public static final TranscodingHints.Key KEY_SCALE_TO_PAGE
          = new BooleanKey(28);
      public static final String KEY_SCALE_TO_PAGE_STR         = "scaleToPage";
  
      public static final String USAGE = "java org.apache.batik.transcoder.print.PrintTranscoder <svgFileToPrint>";
  
      public static void main(String args[]) throws Exception{
          if(args.length < 1){
              System.err.println(USAGE);
              System.exit(0);
          }
  
          //
          // Builds a PrintTranscoder
          //
          PrintTranscoder transcoder = new PrintTranscoder();
  
          //
          // Set the hints, from the command line arguments
          //
  
          // Language
          setTranscoderFloatHint(transcoder, 
                                 KEY_LANGUAGE_STR,
                                 KEY_LANGUAGE);
  
          // User stylesheet
          setTranscoderFloatHint(transcoder, 
                                 KEY_USER_STYLESHEET_URI_STR,
                                 KEY_USER_STYLESHEET_URI);
  
          // XML parser
          setTranscoderStringHint(transcoder, 
                                   KEY_XML_PARSER_CLASSNAME_STR,
                                   KEY_XML_PARSER_CLASSNAME);
  
          // Scale to page
          setTranscoderBooleanHint(transcoder, 
                                   KEY_SCALE_TO_PAGE_STR,
                                   KEY_SCALE_TO_PAGE);
  
          // AOI
          setTranscoderRectangleHint(transcoder,
                                     KEY_AOI_STR,
                                     KEY_AOI);
          
  
          // Image size
          setTranscoderFloatHint(transcoder, 
                                 KEY_WIDTH_STR,
                                 KEY_WIDTH);
          setTranscoderFloatHint(transcoder, 
                                 KEY_HEIGHT_STR,
                                 KEY_HEIGHT);
  
          // Pixel to millimeter
          setTranscoderFloatHint(transcoder,
                                 KEY_PIXEL_TO_MM_STR,
                                 KEY_PIXEL_TO_MM);
  
          // Page orientation
          setTranscoderStringHint(transcoder,
                                  KEY_PAGE_ORIENTATION_STR,
                                  KEY_PAGE_ORIENTATION);
  
          // Page size
          setTranscoderFloatHint(transcoder, 
                                 KEY_PAGE_WIDTH_STR,
                                 KEY_PAGE_WIDTH);
          setTranscoderFloatHint(transcoder, 
                                 KEY_PAGE_HEIGHT_STR,
                                 KEY_PAGE_HEIGHT);
  
          // Margins
          setTranscoderFloatHint(transcoder, 
                                 KEY_MARGIN_TOP_STR,
                                 KEY_MARGIN_TOP);
          setTranscoderFloatHint(transcoder, 
                                 KEY_MARGIN_RIGHT_STR,
                                 KEY_MARGIN_RIGHT);
          setTranscoderFloatHint(transcoder, 
                                 KEY_MARGIN_BOTTOM_STR,
                                 KEY_MARGIN_BOTTOM);
          setTranscoderFloatHint(transcoder, 
                                 KEY_MARGIN_LEFT_STR,
                                 KEY_MARGIN_LEFT);
  
  
          //
          // First, request the transcoder to transcode
          // each of the input files
          //
          for(int i=0; i<args.length; i++){
              transcoder.transcode(new TranscoderInput(new File(args[i]).toURL().toString()),
                                   null);
          }
  
          //
          // Now, print...
          //
          transcoder.print();
      }
  
      public static void setTranscoderFloatHint(Transcoder transcoder,
                                                String property,
                                                TranscodingHints.Key key){
          String str = System.getProperty(property);
          if(str != null){
              try{
                  Float value = new Float(Float.parseFloat(str));
                  transcoder.addTranscodingHint(key, value);
              }catch(NumberFormatException e){
                  handleValueError(property, str);
              }
          }
      }
  
      public static void setTranscoderRectangleHint(Transcoder transcoder,
                                                    String property,
                                                    TranscodingHints.Key key){
          String str = System.getProperty(property);
          if(str != null){
              StringTokenizer st = new StringTokenizer(str, " ,");
              if(st.countTokens() != 4){
                  handleValueError(property, str);
              }
  
              try{
                  String x = st.nextToken();
                  String y = st.nextToken();
                  String width = st.nextToken();
                  String height = st.nextToken();
                  Rectangle2D r = new Rectangle2D.Float(Float.parseFloat(x),
                                                        Float.parseFloat(y),
                                                        Float.parseFloat(width),
                                                        Float.parseFloat(height));
                  transcoder.addTranscodingHint(key, r);
              }catch(NumberFormatException e){
                  handleValueError(property, str);
              }
          }
      }
  
      public static void setTranscoderBooleanHint(Transcoder transcoder,
                                                  String property,
                                                  TranscodingHints.Key key){
          String str = System.getProperty(property);
          if(str != null){
              Boolean value = new Boolean("true".equalsIgnoreCase(str));
              transcoder.addTranscodingHint(key, value);
          }
      }
  
      public static void setTranscoderStringHint(Transcoder transcoder,
                                                String property,
                                                TranscodingHints.Key key){
          String str = System.getProperty(property);
          if(str != null){
              transcoder.addTranscodingHint(key, str);
          }
      }
  
      public static void handleValueError(String property,
                                          String value){
          System.err.println("Invalid " + property + " value : " + value);
          System.exit(1);
      }
  }