diff options
6 files changed, 332 insertions, 22 deletions
diff --git a/src/java/org/apache/fop/image/EmfImage.java b/src/java/org/apache/fop/image/EmfImage.java new file mode 100644 index 000000000..bbe3794c5 --- /dev/null +++ b/src/java/org/apache/fop/image/EmfImage.java @@ -0,0 +1,72 @@ +/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.fop.image;
+
+// Java
+import java.io.ByteArrayOutputStream;
+
+import org.apache.commons.io.IOUtils;
+
+/**
+ * Enhanced metafile image.
+ * This supports loading a emf image.
+ *
+ * @author Peter Herweg
+ * @see AbstractFopImage
+ * @see FopImage
+ */
+public class EmfImage extends AbstractFopImage {
+ /**
+ * Create a bitmap image with the image data.
+ *
+ * @param imgInfo the image information
+ */
+ public EmfImage(FopImage.ImageInfo imgInfo) {
+ super(imgInfo);
+ }
+
+ /**
+ * Load the original jpeg data.
+ * This loads the original jpeg data and reads the color space,
+ * and icc profile if any.
+ *
+ * @return true if loaded false for any error
+ */
+ protected boolean loadOriginalData() {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ try {
+ byte[] readBuf = new byte[4096];
+ int bytesRead;
+ while ((bytesRead = inputStream.read(readBuf)) != -1) {
+ baos.write(readBuf, 0, bytesRead);
+ }
+ } catch (java.io.IOException ex) {
+ log.error("Error while loading image (Emf): " + ex.getMessage(), ex);
+ return false;
+ } finally {
+ IOUtils.closeQuietly(inputStream);
+ inputStream = null;
+ }
+
+ this.raw = baos.toByteArray();
+
+ return true;
+ }
+}
+
diff --git a/src/java/org/apache/fop/image/ImageFactory.java b/src/java/org/apache/fop/image/ImageFactory.java index 8379cda85..d7b73c372 100644 --- a/src/java/org/apache/fop/image/ImageFactory.java +++ b/src/java/org/apache/fop/image/ImageFactory.java @@ -71,6 +71,7 @@ public final class ImageFactory { ImageProvider pngImage = new ImageProvider("PNGImage", "org.apache.fop.image.PNGImage"); ImageProvider tiffImage = new ImageProvider("TIFFImage", "org.apache.fop.image.TIFFImage"); ImageProvider xmlImage = new ImageProvider("XMLImage", "org.apache.fop.image.XMLImage"); + ImageProvider emfImage = new ImageProvider("EMFImage", "org.apache.fop.image.EmfImage"); ImageMimeType imt = new ImageMimeType("image/gif"); imageMimeTypes.put(imt.getMimeType(), imt); @@ -113,7 +114,10 @@ public final class ImageFactory { imt = new ImageMimeType("text/xml"); imageMimeTypes.put(imt.getMimeType(), imt); imt.addProvider(xmlImage); - + + imt = new ImageMimeType("image/emf"); + imageMimeTypes.put(imt.getMimeType(), imt); + imt.addProvider(emfImage); } /** diff --git a/src/java/org/apache/fop/image/analyser/EMFReader.java b/src/java/org/apache/fop/image/analyser/EMFReader.java new file mode 100644 index 000000000..a5c01845f --- /dev/null +++ b/src/java/org/apache/fop/image/analyser/EMFReader.java @@ -0,0 +1,159 @@ +/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.fop.image.analyser;
+
+// Java
+import java.io.InputStream;
+import java.io.IOException;
+
+// FOP
+import org.apache.fop.image.FopImage;
+import org.apache.fop.apps.FOUserAgent;
+
+/**
+ * ImageReader object for EMF image type.
+ *
+ * @author Peter Herweg
+ */
+public class EMFReader implements ImageReader {
+
+ /** Length of the EMF header */
+ protected static final int EMF_SIG_LENGTH = 88;
+
+ /** offset to signature */
+ private static final int SIGNATURE_OFFSET = 40;
+ /** offset to width */
+ private static final int WIDTH_OFFSET = 32;
+ /** offset to height */
+ private static final int HEIGHT_OFFSET = 36;
+ /** offset to horizontal resolution in pixel */
+ private static final int HRES_PIXEL_OFFSET = 72;
+ /** offset to vertical resolution in pixel */
+ private static final int VRES_PIXEL_OFFSET = 76;
+ /** offset to horizontal resolution in mm */
+ private static final int HRES_MM_OFFSET = 80;
+ /** offset to vertical resolution in mm */
+ private static final int VRES_MM_OFFSET = 84;
+
+ /** @see org.apache.fop.image.analyser.ImageReader */
+ public FopImage.ImageInfo verifySignature(String uri, InputStream bis,
+ FOUserAgent ua) throws IOException {
+ byte[] header = getDefaultHeader(bis);
+ boolean supported =
+ ( (header[SIGNATURE_OFFSET + 0] == (byte) 0x20)
+ && (header[SIGNATURE_OFFSET + 1] == (byte) 0x45)
+ && (header[SIGNATURE_OFFSET + 2] == (byte) 0x4D)
+ && (header[SIGNATURE_OFFSET + 3] == (byte) 0x46) );
+
+ if (supported) {
+ FopImage.ImageInfo info = getDimension(header);
+ info.originalURI = uri;
+ info.mimeType = getMimeType();
+ info.inputStream = bis;
+ return info;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the MIME type supported by this implementation.
+ *
+ * @return The MIME type
+ */
+ public String getMimeType() {
+ return "image/emf";
+ }
+
+ private FopImage.ImageInfo getDimension(byte[] header) {
+ FopImage.ImageInfo info = new FopImage.ImageInfo();
+ long value = 0;
+ int byte1;
+ int byte2;
+ int byte3;
+ int byte4;
+
+ // little endian notation
+
+ //resolution
+ byte1 = header[HRES_MM_OFFSET] & 0xff;
+ byte2 = header[HRES_MM_OFFSET + 1] & 0xff;
+ byte3 = header[HRES_MM_OFFSET + 2] & 0xff;
+ byte4 = header[HRES_MM_OFFSET + 3] & 0xff;
+ long hresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1);
+
+ byte1 = header[VRES_MM_OFFSET] & 0xff;
+ byte2 = header[VRES_MM_OFFSET + 1] & 0xff;
+ byte3 = header[VRES_MM_OFFSET + 2] & 0xff;
+ byte4 = header[VRES_MM_OFFSET + 3] & 0xff;
+ long vresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1);
+
+ byte1 = header[HRES_PIXEL_OFFSET] & 0xff;
+ byte2 = header[HRES_PIXEL_OFFSET + 1] & 0xff;
+ byte3 = header[HRES_PIXEL_OFFSET + 2] & 0xff;
+ byte4 = header[HRES_PIXEL_OFFSET + 3] & 0xff;
+ long hresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1);
+
+ byte1 = header[VRES_PIXEL_OFFSET] & 0xff;
+ byte2 = header[VRES_PIXEL_OFFSET + 1] & 0xff;
+ byte3 = header[VRES_PIXEL_OFFSET + 2] & 0xff;
+ byte4 = header[VRES_PIXEL_OFFSET + 3] & 0xff;
+ long vresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1);
+
+ info.dpiHorizontal = hresPixel / (hresMM/25.4);
+ info.dpiVertical = vresPixel / (vresMM/25.4);;
+
+ //width
+ byte1 = header[WIDTH_OFFSET] & 0xff;
+ byte2 = header[WIDTH_OFFSET + 1] & 0xff;
+ byte3 = header[WIDTH_OFFSET + 2] & 0xff;
+ byte4 = header[WIDTH_OFFSET + 3] & 0xff;
+ value = (long) ((byte4 << 24) | (byte3 << 16)
+ | (byte2 << 8) | byte1);
+ value = (long) (value / 100f / 25.4 * info.dpiHorizontal);
+ info.width = (int) (value & 0xffffffff);
+
+ //height
+ byte1 = header[HEIGHT_OFFSET] & 0xff;
+ byte2 = header[HEIGHT_OFFSET + 1] & 0xff;
+ byte3 = header[HEIGHT_OFFSET + 2] & 0xff;
+ byte4 = header[HEIGHT_OFFSET + 3] & 0xff;
+ value = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1);
+ value = (long) (value / 100f / 25.4 * info.dpiVertical);
+ info.height = (int) (value & 0xffffffff);
+
+ return info;
+ }
+
+ private byte[] getDefaultHeader(InputStream imageStream)
+ throws IOException {
+ byte[] header = new byte[EMF_SIG_LENGTH];
+ try {
+ imageStream.mark(EMF_SIG_LENGTH + 1);
+ imageStream.read(header);
+ imageStream.reset();
+ } catch (IOException ex) {
+ try {
+ imageStream.reset();
+ } catch (IOException exbis) {
+ // throw the original exception, not this one
+ }
+ throw ex;
+ }
+ return header;
+ }
+}
diff --git a/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java b/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java index 826f4b60f..853508761 100644 --- a/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java +++ b/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java @@ -50,6 +50,7 @@ public class ImageReaderFactory { registerFormat(new PNGReader()); registerFormat(new TIFFReader()); registerFormat(new EPSReader()); + registerFormat(new EMFReader()); // the xml parser through batik closes the stream when finished // so there is a workaround in the SVGReader registerFormat(new SVGReader()); diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java index 4c08d80e7..6487b5394 100644 --- a/src/java/org/apache/fop/render/rtf/RTFHandler.java +++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.util.Iterator; +import org.apache.fop.*; // Libs import org.apache.commons.logging.Log; @@ -86,6 +87,8 @@ import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfTableContainer; import org.apache.fop.render.rtf.rtflib.tools.BuilderContext; import org.apache.fop.render.rtf.rtflib.tools.TableContext; import org.apache.fop.fonts.FontSetup; +import org.apache.fop.image.FopImage; +import org.apache.fop.image.ImageFactory; /** * RTF Handler: generates RTF output using the structure events from @@ -938,21 +941,72 @@ public class RTFHandler extends FOEventHandler { final RtfExternalGraphic newGraphic = c.getTextrun().newImage(); - //Property p = null; - - //get source file - newGraphic.setURL(eg.getSrc()); + //set URL + String url = eg.getURL(); + newGraphic.setURL(url); + + //set image data + ImageFactory fact = ImageFactory.getInstance(); + FopImage fopimage = fact.getImage(url, eg.getUserAgent()); + fopimage.load(fopimage.ORIGINAL_DATA); - //get scaling + newGraphic.setImageData(fopimage.getRessourceBytes()); + + //set scaling if (eg.getScaling() == Constants.EN_UNIFORM) { newGraphic.setScaling ("uniform"); } //get width - newGraphic.setWidth(eg.getWidth().getValue() / 1000f + "pt"); + int width = 0; + if (eg.getWidth().getEnum() == Constants.EN_AUTO) { + width = fopimage.getIntrinsicWidth(); + } else { + width = eg.getWidth().getValue(); + } //get height - newGraphic.setHeight(eg.getHeight().getValue() / 1000f + "pt"); + int height = 0; + if (eg.getWidth().getEnum() == Constants.EN_AUTO) { + height = fopimage.getIntrinsicHeight(); + } else { + height = eg.getHeight().getValue(); + } + + //get content-width + int contentwidth = 0; + if (eg.getContentWidth().getEnum() + == Constants.EN_AUTO) { + contentwidth = fopimage.getIntrinsicWidth(); + } else if(eg.getContentWidth().getEnum() + == Constants.EN_SCALE_TO_FIT) { + contentwidth = width; + } else { + //TODO: check, if the value is a percent value + contentwidth = eg.getContentWidth().getValue(); + } + + //get content-width + int contentheight = 0; + if (eg.getContentHeight().getEnum() + == Constants.EN_AUTO) { + + contentheight = fopimage.getIntrinsicHeight(); + + } else if(eg.getContentHeight().getEnum() + == Constants.EN_SCALE_TO_FIT) { + + contentheight = height; + } else { + //TODO: check, if the value is a percent value + contentheight = eg.getContentHeight().getValue(); + } + + //set width in rtf + newGraphic.setWidth((long) (contentwidth / 1000f) + "pt"); + + //set height in rtf + newGraphic.setHeight((long) (contentheight / 1000f) + "pt"); //TODO: make this configurable: // int compression = m_context.m_options.getRtfExternalGraphicCompressionRate (); diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java index c34f19b5f..5f0bb1e3d 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java @@ -105,7 +105,6 @@ public class RtfExternalGraphic extends RtfElement { */ public static FormatBase determineFormat(byte[] data) { - int type = ImageConstants.I_NOT_SUPPORTED; if (FormatPNG.isFormat(data)) { return new FormatPNG(); @@ -361,18 +360,19 @@ public class RtfExternalGraphic extends RtfElement { // getRtfFile ().getLog ().logInfo ("Writing image '" + url + "'."); - imagedata = null; - try { - final InputStream in = url.openStream(); + if (imagedata == null) { try { - imagedata = IOUtils.toByteArray(url.openStream()); - } finally { - IOUtils.closeQuietly(in); - } - } catch (Exception e) { - throw new ExternalGraphicException("The attribute 'src' of " - + "<fo:external-graphic> has a invalid value: '" - + url + "' (" + e + ")"); + final InputStream in = url.openStream(); + try { + imagedata = IOUtils.toByteArray(url.openStream()); + } finally { + IOUtils.closeQuietly(in); + } + } catch (Exception e) { + throw new ExternalGraphicException("The attribute 'src' of " + + "<fo:external-graphic> has a invalid value: '" + + url + "' (" + e + ")"); + } } if (imagedata == null) { @@ -463,8 +463,18 @@ public class RtfExternalGraphic extends RtfElement { height = ImageUtil.getIntFromByteArray(imagedata, basis, 2, true); } } else if (imageformat.getType() == ImageConstants.I_EMF) { - width = ImageUtil.getIntFromByteArray(imagedata, 151, 4, false); - height = ImageUtil.getIntFromByteArray(imagedata, 155, 4, false); + int i = 0; + + i = ImageUtil.getIntFromByteArray(imagedata, 151, 4, false); + if (i != 0 ) { + width = i; + } + + i = ImageUtil.getIntFromByteArray(imagedata, 155, 4, false); + if (i != 0 ) { + height = i; + } + } } @@ -546,6 +556,16 @@ public class RtfExternalGraphic extends RtfElement { this.scaleUniform = true; } } + + /** + * Sets the binary imagedata of the image. + * + * @param imagedata Binary imagedata as read from file. + * @throws IOException On error + */ + public void setImageData(byte[] imagedata) throws IOException { + this.imagedata = imagedata; + } /** * Sets the url of the image. |