001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.transcoder.print;
020:
021: import java.awt.Graphics;
022: import java.awt.Graphics2D;
023: import java.awt.RenderingHints;
024: import java.awt.Shape;
025: import java.awt.geom.AffineTransform;
026: import java.awt.geom.Rectangle2D;
027: import java.awt.print.PageFormat;
028: import java.awt.print.Paper;
029: import java.awt.print.Printable;
030: import java.awt.print.PrinterException;
031: import java.awt.print.PrinterJob;
032: import java.io.File;
033: import java.util.StringTokenizer;
034: import java.util.List;
035: import java.util.ArrayList;
036:
037: import org.apache.batik.bridge.BridgeContext;
038: import org.apache.batik.ext.awt.RenderingHintsKeyExt;
039: import org.apache.batik.transcoder.SVGAbstractTranscoder;
040: import org.apache.batik.transcoder.Transcoder;
041: import org.apache.batik.transcoder.TranscoderException;
042: import org.apache.batik.transcoder.TranscoderInput;
043: import org.apache.batik.transcoder.TranscoderOutput;
044: import org.apache.batik.transcoder.TranscodingHints;
045: import org.apache.batik.transcoder.keys.BooleanKey;
046: import org.apache.batik.transcoder.keys.LengthKey;
047: import org.apache.batik.transcoder.keys.StringKey;
048:
049: import org.w3c.dom.Document;
050:
051: /**
052: * This class is a <tt>Transcoder</tt> that prints SVG images.
053: * This class works as follows: any-time the transcode method
054: * is invoked, the corresponding input is cached and nothing
055: * else happens. <br />
056: * However, the <tt>PrintTranscoder</tt> is also a Printable. If used
057: * in a print operation, it will print each of the input
058: * it cached, one input per page.
059: * <br />
060: * The <tt>PrintTranscoder</tt> uses several different hints that
061: * guide its printing:<br />
062: * <ul>
063: * <li><tt>KEY_LANGUAGE, KEY_USER_STYLESHEET_URI, KEY_PIXEL_TO_MM,
064: * KEY_XML_PARSER_CLASSNAME</tt> can be used to set the defaults for
065: * the various SVG properties.</li>
066: * <li><tt>KEY_PAGE_WIDTH, KEY_PAGE_HEIGHT, KEY_MARGIN_TOP, KEY_MARGIN_BOTTOM,
067: * KEY_MARGIN_LEFT, KEY_MARGIN_RIGHT</tt> and <tt>KEY_PAGE_ORIENTATION</tt>
068: * can be used to specify the printing page characteristics.</li>
069: * <li><tt>KEY_WIDTH, KEY_HEIGHT</tt> can be used to specify how to scale the
070: * SVG image</li>
071: * <li><tt>KEY_SCALE_TO_PAGE</tt> can be used to specify whether or not the
072: * SVG image should be scaled uniformly to fit into the printed page or
073: * if it should just be centered into the printed page.</li>
074: * </ul>
075: *
076: * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
077: * @version $Id: PrintTranscoder.java 489226 2006-12-21 00:05:36Z cam $
078: */
079: public class PrintTranscoder extends SVGAbstractTranscoder implements
080: Printable {
081:
082: public static final String KEY_AOI_STR = "aoi";
083: public static final String KEY_HEIGHT_STR = "height";
084: public static final String KEY_LANGUAGE_STR = "language";
085: public static final String KEY_MARGIN_BOTTOM_STR = "marginBottom";
086: public static final String KEY_MARGIN_LEFT_STR = "marginLeft";
087: public static final String KEY_MARGIN_RIGHT_STR = "marginRight";
088: public static final String KEY_MARGIN_TOP_STR = "marginTop";
089: public static final String KEY_PAGE_HEIGHT_STR = "pageHeight";
090: public static final String KEY_PAGE_ORIENTATION_STR = "pageOrientation";
091: public static final String KEY_PAGE_WIDTH_STR = "pageWidth";
092: public static final String KEY_PIXEL_TO_MM_STR = "pixelToMm";
093: public static final String KEY_SCALE_TO_PAGE_STR = "scaleToPage";
094: public static final String KEY_SHOW_PAGE_DIALOG_STR = "showPageDialog";
095: public static final String KEY_SHOW_PRINTER_DIALOG_STR = "showPrinterDialog";
096: public static final String KEY_USER_STYLESHEET_URI_STR = "userStylesheet";
097: public static final String KEY_WIDTH_STR = "width";
098: public static final String KEY_XML_PARSER_CLASSNAME_STR = "xmlParserClassName";
099: public static final String VALUE_MEDIA_PRINT = "print";
100: public static final String VALUE_PAGE_ORIENTATION_LANDSCAPE = "landscape";
101: public static final String VALUE_PAGE_ORIENTATION_PORTRAIT = "portrait";
102: public static final String VALUE_PAGE_ORIENTATION_REVERSE_LANDSCAPE = "reverseLandscape";
103:
104: /**
105: * Set of inputs this transcoder has been requested to
106: * transcode so far.
107: * Purpose is not really clear: some data is added, and it is copied into
108: * printedInputs. But it is never read or cleared...
109: */
110: private List inputs = new ArrayList();
111:
112: /**
113: * Currently printing set of pages. This vector is
114: * created as a clone of inputs when the first page is printed.
115: */
116: private List printedInputs = null;
117:
118: /**
119: * Index of the page corresponding to root
120: */
121: private int curIndex = -1;
122:
123: /**
124: * Place to cache BridgeContext so we can dispose of it when
125: * it is appropriate. The Baseclass would dispose of it too
126: * soon.
127: */
128: private BridgeContext theCtx;
129:
130: /**
131: * Constructs a new transcoder that prints images.
132: */
133: public PrintTranscoder() {
134: super ();
135:
136: hints.put(KEY_MEDIA, VALUE_MEDIA_PRINT);
137: }
138:
139: public void transcode(TranscoderInput in, TranscoderOutput out) {
140: if (in != null) {
141: inputs.add(in);
142: }
143: }
144:
145: /**
146: * Transcodes the specified Document as an image in the specified output.
147: *
148: * @param document the document to transcode
149: * @param uri the uri of the document or null if any
150: * @param output the ouput where to transcode
151: * @exception TranscoderException if an error occured while transcoding
152: */
153: protected void transcode(Document document, String uri,
154: TranscoderOutput output) throws TranscoderException {
155: super .transcode(document, uri, output);
156:
157: // We do this to hide 'ctx' from the SVGAbstractTranscoder
158: // otherwise it will dispose of the context before we can
159: // print the document.
160: theCtx = ctx;
161: ctx = null;
162: }
163:
164: /**
165: * Convenience method
166: */
167: public void print() throws PrinterException {
168: //
169: // Now, request the transcoder to actually perform the
170: // printing job.
171: //
172: PrinterJob printerJob = PrinterJob.getPrinterJob();
173: PageFormat pageFormat = printerJob.defaultPage();
174:
175: //
176: // Set the page parameters from the hints
177: //
178: Paper paper = pageFormat.getPaper();
179:
180: Float pageWidth = (Float) hints.get(KEY_PAGE_WIDTH);
181: Float pageHeight = (Float) hints.get(KEY_PAGE_HEIGHT);
182: if (pageWidth != null) {
183: paper.setSize(pageWidth.floatValue(), paper.getHeight());
184: }
185: if (pageHeight != null) {
186: paper.setSize(paper.getWidth(), pageHeight.floatValue());
187: }
188:
189: float x = 0, y = 0;
190: float width = (float) paper.getWidth();
191: float height = (float) paper.getHeight();
192:
193: Float leftMargin = (Float) hints.get(KEY_MARGIN_LEFT);
194: Float topMargin = (Float) hints.get(KEY_MARGIN_TOP);
195: Float rightMargin = (Float) hints.get(KEY_MARGIN_RIGHT);
196: Float bottomMargin = (Float) hints.get(KEY_MARGIN_BOTTOM);
197:
198: if (leftMargin != null) {
199: x = leftMargin.floatValue();
200: width -= leftMargin.floatValue();
201: }
202: if (topMargin != null) {
203: y = topMargin.floatValue();
204: height -= topMargin.floatValue();
205: }
206: if (rightMargin != null) {
207: width -= rightMargin.floatValue();
208: }
209: if (bottomMargin != null) {
210: height -= bottomMargin.floatValue();
211: }
212:
213: paper.setImageableArea(x, y, width, height);
214:
215: String pageOrientation = (String) hints
216: .get(KEY_PAGE_ORIENTATION);
217: if (VALUE_PAGE_ORIENTATION_PORTRAIT
218: .equalsIgnoreCase(pageOrientation)) {
219: pageFormat.setOrientation(PageFormat.PORTRAIT);
220: } else if (VALUE_PAGE_ORIENTATION_LANDSCAPE
221: .equalsIgnoreCase(pageOrientation)) {
222: pageFormat.setOrientation(PageFormat.LANDSCAPE);
223: } else if (VALUE_PAGE_ORIENTATION_REVERSE_LANDSCAPE
224: .equalsIgnoreCase(pageOrientation)) {
225: pageFormat.setOrientation(PageFormat.REVERSE_LANDSCAPE);
226: }
227:
228: pageFormat.setPaper(paper);
229: pageFormat = printerJob.validatePage(pageFormat);
230:
231: //
232: // If required, pop up a dialog to adjust the page format
233: //
234: Boolean showPageFormat = (Boolean) hints
235: .get(KEY_SHOW_PAGE_DIALOG);
236: if ((showPageFormat != null) && (showPageFormat.booleanValue())) {
237: PageFormat tmpPageFormat = printerJob
238: .pageDialog(pageFormat);
239: if (tmpPageFormat == pageFormat) {
240: // Dialog was cancelled, meaning that the print process should
241: // be stopped.
242: return;
243: }
244:
245: pageFormat = tmpPageFormat;
246: }
247:
248: // Set printable before showing printer dialog so
249: // it can update the pageFormat if it wishes...
250: printerJob.setPrintable(this , pageFormat);
251:
252: //
253: // If required, pop up a dialog to select the printer
254: //
255: Boolean showPrinterDialog;
256: showPrinterDialog = (Boolean) hints
257: .get(KEY_SHOW_PRINTER_DIALOG);
258: if (showPrinterDialog != null
259: && showPrinterDialog.booleanValue()) {
260: if (!printerJob.printDialog()) {
261: // Dialog was cancelled, meaning that the print process
262: // should be stopped.
263: return;
264: }
265: }
266:
267: // Print now
268: printerJob.print();
269:
270: }
271:
272: /**
273: * Printable implementation
274: */
275: public int print(Graphics _g, PageFormat pageFormat, int pageIndex) {
276: //
277: // On the first page, take a snapshot of the vector of
278: // TranscodeInputs.
279: //
280: if (printedInputs == null) {
281: printedInputs = new ArrayList(inputs);
282: }
283:
284: //
285: // If we have already printed each page, return
286: //
287: if (pageIndex >= printedInputs.size()) {
288: curIndex = -1;
289: if (theCtx != null)
290: theCtx.dispose();
291: userAgent.displayMessage("Done");
292: return NO_SUCH_PAGE;
293: }
294:
295: //
296: // Load a new document now if we are printing a new page
297: //
298: if (curIndex != pageIndex) {
299: if (theCtx != null)
300: theCtx.dispose();
301:
302: // The following call will invoke this class' transcode
303: // method which takes a document as an input. That method
304: // builds the GVT root tree.{
305: try {
306: width = (int) pageFormat.getImageableWidth();
307: height = (int) pageFormat.getImageableHeight();
308: super .transcode((TranscoderInput) printedInputs
309: .get(pageIndex), null);
310: curIndex = pageIndex;
311: } catch (TranscoderException e) {
312: drawError(_g, e);
313: return PAGE_EXISTS;
314: }
315: }
316:
317: // Cast to Graphics2D to access Java 2D features
318: Graphics2D g = (Graphics2D) _g;
319: g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
320: RenderingHints.VALUE_ANTIALIAS_ON);
321: g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
322: RenderingHints.VALUE_INTERPOLATION_BILINEAR);
323: g.setRenderingHint(RenderingHintsKeyExt.KEY_TRANSCODING,
324: RenderingHintsKeyExt.VALUE_TRANSCODING_PRINTING);
325:
326: //
327: // Compute transform so that the SVG document fits on one page
328: //
329: AffineTransform t = g.getTransform();
330: Shape clip = g.getClip();
331:
332: // System.err.println("X/Y: " + pageFormat.getImageableX() + ", " +
333: // pageFormat.getImageableY());
334: // System.err.println("W/H: " + width + ", " + height);
335: // System.err.println("Clip: " + clip.getBounds2D());
336:
337: // Offset 0,0 to the start of the imageable Area.
338: g.translate(pageFormat.getImageableX(), pageFormat
339: .getImageableY());
340: //
341: // Append transform to selected area
342: //
343: g.transform(curTxf);
344:
345: //
346: // Delegate rendering to painter
347: //
348: try {
349: root.paint(g);
350: } catch (Exception e) {
351: g.setTransform(t);
352: g.setClip(clip);
353: drawError(_g, e);
354: }
355:
356: //
357: // Restore transform and clip
358: //
359: g.setTransform(t);
360: g.setClip(clip);
361:
362: // g.setPaint(Color.black);
363: // g.drawString(uris[pageIndex], 30, 30);
364:
365: //
366: // Return status indicated that we did paint a page
367: //
368: return PAGE_EXISTS;
369: }
370:
371: /**
372: * Sets document size according to the hints.
373: * Global variables width and height are modified.
374: *
375: * @param docWidth Width of the document.
376: * @param docHeight Height of the document.
377: */
378: protected void setImageSize(float docWidth, float docHeight) {
379: // Check hint to know if scaling is really needed
380: Boolean scaleToPage = (Boolean) hints.get(KEY_SCALE_TO_PAGE);
381: if (scaleToPage != null && !scaleToPage.booleanValue()) {
382: float w = docWidth;
383: float h = docHeight;
384: if (hints.containsKey(KEY_AOI)) {
385: Rectangle2D aoi = (Rectangle2D) hints.get(KEY_AOI);
386: w = (float) aoi.getWidth();
387: h = (float) aoi.getHeight();
388: }
389: super .setImageSize(w, h);
390: }
391: }
392:
393: /**
394: * Prints an error on the output page
395: */
396: private void drawError(Graphics g, Exception e) {
397: userAgent.displayError(e);
398: // Should also probably draw exception on page.
399: }
400:
401: // --------------------------------------------------------------------
402: // Keys definition
403: // --------------------------------------------------------------------
404:
405: /**
406: * The showPageDialog key.
407: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
408: * <TR>
409: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
410: * <TD VALIGN="TOP">KEY_SHOW_PAGE_DIALOG</TD></TR>
411: * <TR>
412: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
413: * <TD VALIGN="TOP">Boolean</TD></TR>
414: * <TR>
415: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
416: * <TD VALIGN="TOP">false</TD></TR>
417: * <TR>
418: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
419: * <TD VALIGN="TOP">No</TD></TR>
420: * <TR>
421: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
422: * <TD VALIGN="TOP">Specifies whether or not the transcoder
423: * should pop up a dialog box for selecting
424: * the page format.</TD></TR>
425: * </TABLE> */
426: public static final TranscodingHints.Key KEY_SHOW_PAGE_DIALOG = new BooleanKey();
427:
428: /**
429: * The showPrinterDialog key.
430: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
431: * <TR>
432: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
433: * <TD VALIGN="TOP">KEY_SHOW_PAGE_DIALOG</TD></TR>
434: * <TR>
435: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
436: * <TD VALIGN="TOP">Boolean</TD></TR>
437: * <TR>
438: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
439: * <TD VALIGN="TOP">false</TD></TR>
440: * <TR>
441: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
442: * <TD VALIGN="TOP">No</TD></TR>
443: * <TR>
444: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
445: * <TD VALIGN="TOP">Specifies whether or not the transcoder
446: * should pop up a dialog box for selecting
447: * the printer. If the dialog box is not
448: * shown, the transcoder will use the default
449: * printer.</TD></TR>
450: * </TABLE> */
451: public static final TranscodingHints.Key KEY_SHOW_PRINTER_DIALOG = new BooleanKey();
452:
453: /**
454: * The pageWidth key.
455: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
456: * <TR>
457: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
458: * <TD VALIGN="TOP">KEY_PAGE_WIDTH</TD></TR>
459: * <TR>
460: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
461: * <TD VALIGN="TOP">Length</TD></TR>
462: * <TR>
463: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
464: * <TD VALIGN="TOP">None</TD></TR>
465: * <TR>
466: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
467: * <TD VALIGN="TOP">No</TD></TR>
468: * <TR>
469: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
470: * <TD VALIGN="TOP">The width of the print page</TD></TR>
471: * </TABLE> */
472: public static final TranscodingHints.Key KEY_PAGE_WIDTH = new LengthKey();
473:
474: /**
475: * The pageHeight key.
476: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
477: * <TR>
478: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
479: * <TD VALIGN="TOP">KEY_PAGE_HEIGHT</TD></TR>
480: * <TR>
481: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
482: * <TD VALIGN="TOP">Length</TD></TR>
483: * <TR>
484: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
485: * <TD VALIGN="TOP">None</TD></TR>
486: * <TR>
487: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
488: * <TD VALIGN="TOP">No</TD></TR>
489: * <TR>
490: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
491: * <TD VALIGN="TOP">The height of the print page</TD></TR>
492: * </TABLE> */
493: public static final TranscodingHints.Key KEY_PAGE_HEIGHT = new LengthKey();
494:
495: /**
496: * The marginTop key.
497: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
498: * <TR>
499: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
500: * <TD VALIGN="TOP">KEY_MARGIN_TOP</TD></TR>
501: * <TR>
502: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
503: * <TD VALIGN="TOP">Length</TD></TR>
504: * <TR>
505: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
506: * <TD VALIGN="TOP">None</TD></TR>
507: * <TR>
508: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
509: * <TD VALIGN="TOP">No</TD></TR>
510: * <TR>
511: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
512: * <TD VALIGN="TOP">The print page top margin</TD></TR>
513: * </TABLE> */
514: public static final TranscodingHints.Key KEY_MARGIN_TOP = new LengthKey();
515:
516: /**
517: * The marginRight key.
518: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
519: * <TR>
520: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
521: * <TD VALIGN="TOP">KEY_MARGIN_RIGHT</TD></TR>
522: * <TR>
523: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
524: * <TD VALIGN="TOP">Length</TD></TR>
525: * <TR>
526: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
527: * <TD VALIGN="TOP">None</TD></TR>
528: * <TR>
529: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
530: * <TD VALIGN="TOP">No</TD></TR>
531: * <TR>
532: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
533: * <TD VALIGN="TOP">The print page right margin</TD></TR>
534: * </TABLE> */
535: public static final TranscodingHints.Key KEY_MARGIN_RIGHT = new LengthKey();
536:
537: /**
538: * The marginBottom key.
539: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
540: * <TR>
541: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
542: * <TD VALIGN="TOP">KEY_MARGIN_BOTTOM</TD></TR>
543: * <TR>
544: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
545: * <TD VALIGN="TOP">Length</TD></TR>
546: * <TR>
547: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
548: * <TD VALIGN="TOP">None</TD></TR>
549: * <TR>
550: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
551: * <TD VALIGN="TOP">No</TD></TR>
552: * <TR>
553: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
554: * <TD VALIGN="TOP">The print page bottom margin</TD></TR>
555: * </TABLE> */
556: public static final TranscodingHints.Key KEY_MARGIN_BOTTOM = new LengthKey();
557:
558: /**
559: * The marginLeft key.
560: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
561: * <TR>
562: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
563: * <TD VALIGN="TOP">KEY_MARGIN_LEFT</TD></TR>
564: * <TR>
565: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
566: * <TD VALIGN="TOP">Length</TD></TR>
567: * <TR>
568: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
569: * <TD VALIGN="TOP">None</TD></TR>
570: * <TR>
571: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
572: * <TD VALIGN="TOP">No</TD></TR>
573: * <TR>
574: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
575: * <TD VALIGN="TOP">The print page left margin</TD></TR>
576: * </TABLE> */
577: public static final TranscodingHints.Key KEY_MARGIN_LEFT = new LengthKey();
578:
579: /**
580: * The pageOrientation key.
581: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
582: * <TR>
583: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
584: * <TD VALIGN="TOP">KEY_PAGE_ORIENTATION</TD></TR>
585: * <TR>
586: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
587: * <TD VALIGN="TOP">String</TD></TR>
588: * <TR>
589: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
590: * <TD VALIGN="TOP">VALUE_PAGE_ORIENTATION_PORTRAIT</TD></TR>
591: * <TR>
592: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
593: * <TD VALIGN="TOP">No</TD></TR>
594: * <TR>
595: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
596: * <TD VALIGN="TOP">The print page's orientation</TD></TR>
597: * </TABLE> */
598: public static final TranscodingHints.Key KEY_PAGE_ORIENTATION = new StringKey();
599:
600: /**
601: * The scaleToPage key.
602: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
603: * <TR>
604: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
605: * <TD VALIGN="TOP">KEY_SCALE_TO_PAGE</TD></TR>
606: * <TR>
607: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
608: * <TD VALIGN="TOP">Boolean</TD></TR>
609: * <TR>
610: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
611: * <TD VALIGN="TOP">true</TD></TR>
612: * <TR>
613: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
614: * <TD VALIGN="TOP">No</TD></TR>
615: * <TR>
616: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
617: * <TD VALIGN="TOP">Specifies whether or not the SVG images are scaled to
618: * fit into the printed page</TD></TR>
619: * </TABLE> */
620: public static final TranscodingHints.Key KEY_SCALE_TO_PAGE = new BooleanKey();
621:
622: public static final String USAGE = "java org.apache.batik.transcoder.print.PrintTranscoder <svgFileToPrint>";
623:
624: public static void main(String[] args) throws Exception {
625: if (args.length < 1) {
626: System.err.println(USAGE);
627: System.exit(0);
628: }
629:
630: //
631: // Builds a PrintTranscoder
632: //
633: PrintTranscoder transcoder = new PrintTranscoder();
634:
635: //
636: // Set the hints, from the command line arguments
637: //
638:
639: // Language
640: setTranscoderFloatHint(transcoder, KEY_LANGUAGE_STR,
641: KEY_LANGUAGE);
642:
643: // User stylesheet
644: setTranscoderFloatHint(transcoder, KEY_USER_STYLESHEET_URI_STR,
645: KEY_USER_STYLESHEET_URI);
646:
647: // XML parser
648: setTranscoderStringHint(transcoder,
649: KEY_XML_PARSER_CLASSNAME_STR, KEY_XML_PARSER_CLASSNAME);
650:
651: // Scale to page
652: setTranscoderBooleanHint(transcoder, KEY_SCALE_TO_PAGE_STR,
653: KEY_SCALE_TO_PAGE);
654:
655: // AOI
656: setTranscoderRectangleHint(transcoder, KEY_AOI_STR, KEY_AOI);
657:
658: // Image size
659: setTranscoderFloatHint(transcoder, KEY_WIDTH_STR, KEY_WIDTH);
660: setTranscoderFloatHint(transcoder, KEY_HEIGHT_STR, KEY_HEIGHT);
661:
662: // Pixel to millimeter
663: setTranscoderFloatHint(transcoder, KEY_PIXEL_TO_MM_STR,
664: KEY_PIXEL_UNIT_TO_MILLIMETER);
665:
666: // Page orientation
667: setTranscoderStringHint(transcoder, KEY_PAGE_ORIENTATION_STR,
668: KEY_PAGE_ORIENTATION);
669:
670: // Page size
671: setTranscoderFloatHint(transcoder, KEY_PAGE_WIDTH_STR,
672: KEY_PAGE_WIDTH);
673: setTranscoderFloatHint(transcoder, KEY_PAGE_HEIGHT_STR,
674: KEY_PAGE_HEIGHT);
675:
676: // Margins
677: setTranscoderFloatHint(transcoder, KEY_MARGIN_TOP_STR,
678: KEY_MARGIN_TOP);
679: setTranscoderFloatHint(transcoder, KEY_MARGIN_RIGHT_STR,
680: KEY_MARGIN_RIGHT);
681: setTranscoderFloatHint(transcoder, KEY_MARGIN_BOTTOM_STR,
682: KEY_MARGIN_BOTTOM);
683: setTranscoderFloatHint(transcoder, KEY_MARGIN_LEFT_STR,
684: KEY_MARGIN_LEFT);
685:
686: // Dialog options
687: setTranscoderBooleanHint(transcoder, KEY_SHOW_PAGE_DIALOG_STR,
688: KEY_SHOW_PAGE_DIALOG);
689:
690: setTranscoderBooleanHint(transcoder,
691: KEY_SHOW_PRINTER_DIALOG_STR, KEY_SHOW_PRINTER_DIALOG);
692:
693: //
694: // First, request the transcoder to transcode
695: // each of the input files
696: //
697: for (int i = 0; i < args.length; i++) {
698: transcoder.transcode(new TranscoderInput(new File(args[i])
699: .toURL().toString()), null);
700: }
701:
702: //
703: // Now, print...
704: //
705: transcoder.print();
706:
707: System.exit(0);
708: }
709:
710: public static void setTranscoderFloatHint(Transcoder transcoder,
711: String property, TranscodingHints.Key key) {
712: String str = System.getProperty(property);
713: if (str != null) {
714: try {
715: Float value = new Float(Float.parseFloat(str));
716: transcoder.addTranscodingHint(key, value);
717: } catch (NumberFormatException e) {
718: handleValueError(property, str);
719: }
720: }
721: }
722:
723: public static void setTranscoderRectangleHint(
724: Transcoder transcoder, String property,
725: TranscodingHints.Key key) {
726: String str = System.getProperty(property);
727: if (str != null) {
728: StringTokenizer st = new StringTokenizer(str, " ,");
729: if (st.countTokens() != 4) {
730: handleValueError(property, str);
731: }
732:
733: try {
734: String x = st.nextToken();
735: String y = st.nextToken();
736: String width = st.nextToken();
737: String height = st.nextToken();
738: Rectangle2D r = new Rectangle2D.Float(Float
739: .parseFloat(x), Float.parseFloat(y), Float
740: .parseFloat(width), Float.parseFloat(height));
741: transcoder.addTranscodingHint(key, r);
742: } catch (NumberFormatException e) {
743: handleValueError(property, str);
744: }
745: }
746: }
747:
748: public static void setTranscoderBooleanHint(Transcoder transcoder,
749: String property, TranscodingHints.Key key) {
750: String str = System.getProperty(property);
751: if (str != null) {
752: Boolean value = "true".equalsIgnoreCase(str) ? Boolean.TRUE
753: : Boolean.FALSE;
754: transcoder.addTranscodingHint(key, value);
755: }
756: }
757:
758: public static void setTranscoderStringHint(Transcoder transcoder,
759: String property, TranscodingHints.Key key) {
760: String str = System.getProperty(property);
761: if (str != null) {
762: transcoder.addTranscodingHint(key, str);
763: }
764: }
765:
766: public static void handleValueError(String property, String value) {
767: System.err.println("Invalid " + property + " value : " + value);
768: System.exit(1);
769: }
770: }
|