001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: PDFTranscoder.java 542237 2007-05-28 14:31:24Z jeremias $ */
019:
020: package org.apache.fop.svg;
021:
022: import java.awt.Color;
023: import java.io.IOException;
024:
025: import org.apache.avalon.framework.configuration.Configurable;
026: import org.apache.avalon.framework.configuration.Configuration;
027: import org.apache.avalon.framework.configuration.ConfigurationException;
028: import org.apache.batik.bridge.BridgeContext;
029: import org.apache.batik.bridge.UnitProcessor;
030: import org.apache.batik.bridge.UserAgent;
031: import org.apache.batik.ext.awt.RenderingHintsKeyExt;
032: import org.apache.batik.transcoder.TranscoderException;
033: import org.apache.batik.transcoder.TranscoderOutput;
034: import org.apache.batik.transcoder.TranscodingHints;
035: import org.apache.batik.transcoder.image.ImageTranscoder;
036: import org.apache.batik.transcoder.keys.FloatKey;
037: import org.apache.fop.Version;
038: import org.apache.fop.fonts.FontInfo;
039: import org.apache.fop.fonts.FontSetup;
040: import org.w3c.dom.Document;
041: import org.w3c.dom.svg.SVGLength;
042:
043: /**
044: * This class enables to transcode an input to a pdf document.
045: *
046: * <p>Two transcoding hints (<tt>KEY_WIDTH</tt> and
047: * <tt>KEY_HEIGHT</tt>) can be used to respectively specify the image
048: * width and the image height. If only one of these keys is specified,
049: * the transcoder preserves the aspect ratio of the original image.
050: *
051: * <p>The <tt>KEY_BACKGROUND_COLOR</tt> defines the background color
052: * to use for opaque image formats, or the background color that may
053: * be used for image formats that support alpha channel.
054: *
055: * <p>The <tt>KEY_AOI</tt> represents the area of interest to paint
056: * in device space.
057: *
058: * <p>Three additional transcoding hints that act on the SVG
059: * processor can be specified:
060: *
061: * <p><tt>KEY_LANGUAGE</tt> to set the default language to use (may be
062: * used by a <switch> SVG element for example),
063: * <tt>KEY_USER_STYLESHEET_URI</tt> to fix the URI of a user
064: * stylesheet, and <tt>KEY_PIXEL_TO_MM</tt> to specify the pixel to
065: * millimeter conversion factor.
066: *
067: * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
068: * @version $Id: PDFTranscoder.java 542237 2007-05-28 14:31:24Z jeremias $
069: */
070: public class PDFTranscoder extends AbstractFOPTranscoder implements
071: Configurable {
072:
073: /**
074: * The key is used to specify the resolution for on-the-fly images generated
075: * due to complex effects like gradients and filters.
076: */
077: public static final TranscodingHints.Key KEY_DEVICE_RESOLUTION = new FloatKey();
078:
079: private Configuration cfg = null;
080:
081: /** Graphics2D instance that is used to paint to */
082: protected PDFDocumentGraphics2D graphics = null;
083:
084: /**
085: * Constructs a new <tt>ImageTranscoder</tt>.
086: */
087: public PDFTranscoder() {
088: super ();
089: this .handler = new FOPErrorHandler();
090: }
091:
092: /**
093: * @see org.apache.fop.svg.AbstractFOPTranscoder#createUserAgent()
094: */
095: protected UserAgent createUserAgent() {
096: return new AbstractFOPTranscoder.FOPTranscoderUserAgent() {
097: // The PDF stuff wants everything at 72dpi
098: public float getPixelUnitToMillimeter() {
099: return super .getPixelUnitToMillimeter();
100: //return 25.4f / 72; //72dpi = 0.352778f;
101: }
102: };
103: }
104:
105: /**
106: * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
107: */
108: public void configure(Configuration cfg)
109: throws ConfigurationException {
110: this .cfg = cfg;
111: }
112:
113: /**
114: * Transcodes the specified Document as an image in the specified output.
115: *
116: * @param document the document to transcode
117: * @param uri the uri of the document or null if any
118: * @param output the ouput where to transcode
119: * @exception TranscoderException if an error occured while transcoding
120: */
121: protected void transcode(Document document, String uri,
122: TranscoderOutput output) throws TranscoderException {
123:
124: graphics = new PDFDocumentGraphics2D();
125: graphics.getPDFDocument().getInfo().setProducer(
126: "Apache FOP Version " + Version.getVersion()
127: + ": PDF Transcoder for Batik");
128:
129: try {
130: if (this .cfg != null) {
131: PDFDocumentGraphics2DConfigurator configurator = new PDFDocumentGraphics2DConfigurator();
132: configurator.configure(graphics, this .cfg);
133: }
134: } catch (Exception e) {
135: throw new TranscoderException(
136: "Error while setting up PDFDocumentGraphics2D", e);
137: }
138:
139: super .transcode(document, uri, output);
140:
141: if (getLogger().isTraceEnabled()) {
142: getLogger().trace(
143: "document size: " + width + " x " + height);
144: }
145:
146: // prepare the image to be painted
147: UnitProcessor.Context uctx = UnitProcessor.createContext(ctx,
148: document.getDocumentElement());
149: float widthInPt = UnitProcessor.userSpaceToSVG(width,
150: SVGLength.SVG_LENGTHTYPE_PT,
151: UnitProcessor.HORIZONTAL_LENGTH, uctx);
152: int w = (int) (widthInPt + 0.5);
153: float heightInPt = UnitProcessor.userSpaceToSVG(height,
154: SVGLength.SVG_LENGTHTYPE_PT,
155: UnitProcessor.HORIZONTAL_LENGTH, uctx);
156: int h = (int) (heightInPt + 0.5);
157: if (getLogger().isTraceEnabled()) {
158: getLogger().trace(
159: "document size: " + w + "pt x " + h + "pt");
160: }
161:
162: // prepare the image to be painted
163: //int w = (int)(width + 0.5);
164: //int h = (int)(height + 0.5);
165:
166: try {
167: if (hints.containsKey(KEY_DEVICE_RESOLUTION)) {
168: graphics.setDeviceDPI(((Float) hints
169: .get(KEY_DEVICE_RESOLUTION)).floatValue());
170: }
171: graphics.setupDocument(output.getOutputStream(), w, h);
172: graphics.setSVGDimension(width, height);
173:
174: if (hints.containsKey(ImageTranscoder.KEY_BACKGROUND_COLOR)) {
175: graphics.setBackgroundColor((Color) hints
176: .get(ImageTranscoder.KEY_BACKGROUND_COLOR));
177: }
178: graphics
179: .setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
180: graphics.preparePainting();
181:
182: graphics.transform(curTxf);
183: graphics.setRenderingHint(
184: RenderingHintsKeyExt.KEY_TRANSCODING,
185: RenderingHintsKeyExt.VALUE_TRANSCODING_VECTOR);
186:
187: this .root.paint(graphics);
188:
189: graphics.finish();
190: } catch (IOException ex) {
191: throw new TranscoderException(ex);
192: }
193: }
194:
195: /** @see org.apache.batik.transcoder.SVGAbstractTranscoder#createBridgeContext() */
196: protected BridgeContext createBridgeContext() {
197: BridgeContext ctx = new PDFBridgeContext(userAgent, graphics
198: .getFontInfo());
199: return ctx;
200: }
201:
202: }
|