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:
020: package org.apache.batik.transcoder.wmf.tosvg;
021:
022: import java.awt.Dimension;
023: import java.io.BufferedInputStream;
024: import java.io.DataInputStream;
025: import java.io.File;
026: import java.io.FileOutputStream;
027: import java.io.IOException;
028: import java.io.InputStream;
029: import java.net.MalformedURLException;
030: import java.net.URL;
031:
032: import org.apache.batik.svggen.SVGGraphics2D;
033: import org.apache.batik.transcoder.ToSVGAbstractTranscoder;
034: import org.apache.batik.transcoder.TranscoderException;
035: import org.apache.batik.transcoder.TranscoderInput;
036: import org.apache.batik.transcoder.TranscoderOutput;
037:
038: import org.w3c.dom.Document;
039: import org.w3c.dom.Element;
040:
041: /** This class implements the <tt>Transcoder</tt> interface and
042: * can convert a WMF input document into an SVG document.
043: * <p>This class is copied from
044: * batik org.apache.batik.transcoder.wmf.tosvg.WMFTranscoder class.</p>
045: * <p>It can use <tt>TranscoderInput</tt> that are either a URI
046: * or a <tt>InputStream</tt> or a <tt>Reader</tt>. The
047: * <tt>XMLReader</tt> and <tt>Document</tt> <tt>TranscoderInput</tt>
048: * types are not supported.</p>
049: *
050: * <p>This transcoder can use <tt>TranscoderOutputs</tt> that are
051: * of any type except the <tt>XMLFilter</tt> type.</p>
052: *
053: * <p>Corrected bugs from the original class:</p>
054: * <ul>
055: * <li> Manage images size</li>
056: * </ul>
057: * <p>Exemple of use :</p>
058: * <pre>
059: * WMFTranscoder transcoder = new WMFTranscoder();
060: * try {
061: * TranscoderInput wmf = new TranscoderInput(wmffile.toURL().toString());
062: * TranscoderOutput svg = new TranscoderOutput(new FileOutputStream(svgFile));
063: * transcoder.transcode(wmf, svg);
064: * } catch (MalformedURLException e){
065: * throw new TranscoderException(e);
066: * } catch (IOException e){
067: * throw new TranscoderException(e);
068: * }
069: * </pre>
070: * <p>Several transcoding hints are available for this transcoder :</p>
071: * <ul>
072: * <li>KEY_INPUT_WIDTH, KEY_INPUT_HEIGHT, KEY_XOFFSET, KEY_YOFFSET : this Integer values allows to
073: * set the portion of the image to transcode, defined by the width, height, and offset
074: * of this portion in Metafile units.
075: * </ul>
076: * <pre>
077: * transcoder.addTranscodingHint(FromWMFTranscoder.KEY_INPUT_WIDTH, new Integer(input_width));
078: * </pre>
079: * </li>
080: * <li>KEY_WIDTH, KEY_HEIGHT : this Float values allows to force the width and height of the output:
081: * </ul>
082: * <pre>
083: * transcoder.addTranscodingHint(FromWMFTranscoder.KEY_WIDTH, new Float(width));
084: * </pre>
085: * </li>
086: * </ul>
087: *
088: * @version $Id: WMFTranscoder.java 501495 2007-01-30 18:00:36Z dvholten $
089: */
090: public class WMFTranscoder extends ToSVGAbstractTranscoder {
091:
092: /**
093: * Default constructor
094: */
095: public WMFTranscoder() {
096: }
097:
098: /**
099: * Transcodes the specified input in the specified output.
100: * @param input the input to transcode
101: * @param output the ouput where to transcode
102: * @exception TranscoderException if an error occured while transcoding
103: */
104: public void transcode(TranscoderInput input, TranscoderOutput output)
105: throws TranscoderException {
106: //
107: // Extract the input
108: //
109: DataInputStream is = getCompatibleInput(input);
110:
111: //
112: // Build a RecordStore from the input
113: //
114: WMFRecordStore currentStore = new WMFRecordStore();
115: try {
116: currentStore.read(is);
117: } catch (IOException e) {
118: handler.fatalError(new TranscoderException(e));
119: return;
120: }
121:
122: // determines the width and height of output image
123: float wmfwidth; // width in pixels
124: float wmfheight; // height in pixels
125: float conv = 1.0f; // conversion factor
126:
127: if (hints.containsKey(KEY_INPUT_WIDTH)) {
128: wmfwidth = ((Integer) hints.get(KEY_INPUT_WIDTH))
129: .intValue();
130: wmfheight = ((Integer) hints.get(KEY_INPUT_HEIGHT))
131: .intValue();
132: } else {
133: wmfwidth = currentStore.getWidthPixels();
134: wmfheight = currentStore.getHeightPixels();
135: }
136: float width = wmfwidth;
137: float height = wmfheight;
138:
139: // change the output width and height if required
140: if (hints.containsKey(KEY_WIDTH)) {
141: width = ((Float) hints.get(KEY_WIDTH)).floatValue();
142: conv = width / wmfwidth;
143: height = height * width / wmfwidth;
144: }
145:
146: // determine the offset values
147: int xOffset = 0;
148: int yOffset = 0;
149: if (hints.containsKey(KEY_XOFFSET)) {
150: xOffset = ((Integer) hints.get(KEY_XOFFSET)).intValue();
151: }
152: if (hints.containsKey(KEY_YOFFSET)) {
153: yOffset = ((Integer) hints.get(KEY_YOFFSET)).intValue();
154: }
155:
156: // Set the size and viewBox on the output document
157: float sizeFactor = currentStore.getUnitsToPixels() * conv;
158:
159: int vpX = (int) (currentStore.getVpX() * sizeFactor);
160: int vpY = (int) (currentStore.getVpY() * sizeFactor);
161:
162: int vpW;
163: int vpH;
164: // if we took only a part of the image, we use its dimension for computing
165: if (hints.containsKey(KEY_INPUT_WIDTH)) {
166: vpW = (int) (((Integer) hints.get(KEY_INPUT_WIDTH))
167: .intValue() * conv);
168: vpH = (int) (((Integer) hints.get(KEY_INPUT_HEIGHT))
169: .intValue() * conv);
170: // else we took the whole image dimension
171: } else {
172: vpW = (int) (currentStore.getWidthUnits() * sizeFactor);
173: vpH = (int) (currentStore.getHeightUnits() * sizeFactor);
174: }
175:
176: // Build a painter for the RecordStore
177: WMFPainter painter = new WMFPainter(currentStore, xOffset,
178: yOffset, conv);
179:
180: // Use SVGGraphics2D to generate SVG content
181: Document doc = this .createDocument(output);
182: svgGenerator = new SVGGraphics2D(doc);
183:
184: /** set precision
185: ** otherwise Ellipses aren't working (for example) (because of Decimal format
186: * modifications ins SVGGenerator Context
187: */
188: svgGenerator.getGeneratorContext().setPrecision(4);
189:
190: painter.paint(svgGenerator);
191:
192: svgGenerator.setSVGCanvasSize(new Dimension(vpW, vpH));
193:
194: Element svgRoot = svgGenerator.getRoot();
195:
196: svgRoot.setAttributeNS(null, SVG_VIEW_BOX_ATTRIBUTE, String
197: .valueOf(vpX)
198: + ' ' + vpY + ' ' + vpW + ' ' + vpH);
199:
200: // Now, write the SVG content to the output
201: writeSVGToOutput(svgGenerator, svgRoot, output);
202: }
203:
204: /**
205: * Checks that the input is one of URI or an <tt>InputStream</tt>
206: * returns it as a DataInputStream
207: */
208: private DataInputStream getCompatibleInput(TranscoderInput input)
209: throws TranscoderException {
210: // Cannot deal with null input
211: if (input == null) {
212: handler.fatalError(new TranscoderException(String
213: .valueOf(ERROR_NULL_INPUT)));
214: }
215:
216: // Can deal with InputStream
217: InputStream in = input.getInputStream();
218: if (in != null) {
219: return new DataInputStream(new BufferedInputStream(in));
220: }
221:
222: // Can deal with URI
223: String uri = input.getURI();
224: if (uri != null) {
225: try {
226: URL url = new URL(uri);
227: in = url.openStream();
228: return new DataInputStream(new BufferedInputStream(in));
229: } catch (MalformedURLException e) {
230: handler.fatalError(new TranscoderException(e));
231: } catch (IOException e) {
232: handler.fatalError(new TranscoderException(e));
233: }
234: }
235:
236: handler.fatalError(new TranscoderException(String
237: .valueOf(ERROR_INCOMPATIBLE_INPUT_TYPE)));
238: return null;
239: }
240:
241: public static final String WMF_EXTENSION = ".wmf";
242: public static final String SVG_EXTENSION = ".svg";
243:
244: /**
245: * Unit testing : Illustrates how the transcoder might be used.
246: */
247: public static void main(String[] args) throws TranscoderException {
248: if (args.length < 1) {
249: System.out
250: .println("Usage : WMFTranscoder.main <file 1> ... <file n>");
251: System.exit(1);
252: }
253:
254: WMFTranscoder transcoder = new WMFTranscoder();
255: int nFiles = args.length;
256:
257: for (int i = 0; i < nFiles; i++) {
258: String fileName = args[i];
259: if (!fileName.toLowerCase().endsWith(WMF_EXTENSION)) {
260: System.err.println(args[i] + " does not have the "
261: + WMF_EXTENSION + " extension. It is ignored");
262: } else {
263: System.out.print("Processing : " + args[i] + "...");
264: String outputFileName = fileName.substring(0, fileName
265: .toLowerCase().indexOf(WMF_EXTENSION))
266: + SVG_EXTENSION;
267: File inputFile = new File(fileName);
268: File outputFile = new File(outputFileName);
269: try {
270: TranscoderInput input = new TranscoderInput(
271: inputFile.toURL().toString());
272: TranscoderOutput output = new TranscoderOutput(
273: new FileOutputStream(outputFile));
274: transcoder.transcode(input, output);
275: } catch (MalformedURLException e) {
276: throw new TranscoderException(e);
277: } catch (IOException e) {
278: throw new TranscoderException(e);
279: }
280: System.out.println(".... Done");
281: }
282: }
283:
284: System.exit(0);
285: }
286: }
|