Switching to code in XML Graphics Commons for: - PSGraphics2D - Service discovery - Codecs Removed local classes that have been ported to Commons. xmlgraphics-commons-snapshot.jar is a Trunk snapshot built with JDK 1.4.2 from today. It should work under JDK 1.3.1. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@391332 13f79535-47bb-0310-9956-ffa450edef68pull/35/head
<fileset dir="${basedir}" id="dist.bin.lib"> | <fileset dir="${basedir}" id="dist.bin.lib"> | ||||
<patternset id="dist.lib"> | <patternset id="dist.lib"> | ||||
<include name="lib/avalon-framework*"/> | <include name="lib/avalon-framework*"/> | ||||
<include name="lib/xmlgraphics-commons*"/> | |||||
<include name="lib/batik*"/> | <include name="lib/batik*"/> | ||||
<include name="lib/commons-io*"/> | <include name="lib/commons-io*"/> | ||||
<include name="lib/commons-logging*"/> | <include name="lib/commons-logging*"/> | ||||
<include name="commons-io*.jar"/> | <include name="commons-io*.jar"/> | ||||
<include name="avalon-framework*.jar"/> | <include name="avalon-framework*.jar"/> | ||||
<include name="commons-logging*.jar"/> | <include name="commons-logging*.jar"/> | ||||
<include name="xmlgraphics*.jar"/> | |||||
<include name="xmlgraphics-commons*.jar"/> | |||||
</fileset> | </fileset> | ||||
<target name="uptodate-transcoder-pkg" depends="compile-java"> | <target name="uptodate-transcoder-pkg" depends="compile-java"> | ||||
<include name="org/apache/commons/io/output/ProxyOutputStream.class"/> | <include name="org/apache/commons/io/output/ProxyOutputStream.class"/> | ||||
<include name="org/apache/commons/io/output/ByteArrayOutputStream.class"/> | <include name="org/apache/commons/io/output/ByteArrayOutputStream.class"/> | ||||
<include name="org/apache/commons/io/output/CountingOutputStream.class"/> | <include name="org/apache/commons/io/output/CountingOutputStream.class"/> | ||||
<!-- TODO Remove the following lines once Batik switches over to using XML Graphics Commons --> | |||||
<include name="org/apache/xmlgraphics/java2d/**"/> | |||||
<include name="org/apache/xmlgraphics/ps/**"/> | |||||
<include name="org/apache/xmlgraphics/fonts/**"/> | |||||
<include name="org/apache/xmlgraphics/util/io/**"/> | |||||
</patternset> | </patternset> | ||||
<fileset refid="transcoder-lib-files"/> | <fileset refid="transcoder-lib-files"/> | ||||
</unjar> | </unjar> |
Apache License v2.0 | Apache License v2.0 | ||||
- Apache XML Graphics Commons | |||||
xmlgraphics-commons-*.jar | |||||
http://xmlgraphics.apache.org/ | |||||
(Common Library for Apache Batik and Apache FOP) | |||||
Apache License v2.0 | |||||
- Apache Batik | - Apache Batik | ||||
batik-*.jar | batik-*.jar |
Apache License | |||||
Version 2.0, January 2004 | |||||
http://www.apache.org/licenses/ | |||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |||||
1. Definitions. | |||||
"License" shall mean the terms and conditions for use, reproduction, | |||||
and distribution as defined by Sections 1 through 9 of this document. | |||||
"Licensor" shall mean the copyright owner or entity authorized by | |||||
the copyright owner that is granting the License. | |||||
"Legal Entity" shall mean the union of the acting entity and all | |||||
other entities that control, are controlled by, or are under common | |||||
control with that entity. For the purposes of this definition, | |||||
"control" means (i) the power, direct or indirect, to cause the | |||||
direction or management of such entity, whether by contract or | |||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the | |||||
outstanding shares, or (iii) beneficial ownership of such entity. | |||||
"You" (or "Your") shall mean an individual or Legal Entity | |||||
exercising permissions granted by this License. | |||||
"Source" form shall mean the preferred form for making modifications, | |||||
including but not limited to software source code, documentation | |||||
source, and configuration files. | |||||
"Object" form shall mean any form resulting from mechanical | |||||
transformation or translation of a Source form, including but | |||||
not limited to compiled object code, generated documentation, | |||||
and conversions to other media types. | |||||
"Work" shall mean the work of authorship, whether in Source or | |||||
Object form, made available under the License, as indicated by a | |||||
copyright notice that is included in or attached to the work | |||||
(an example is provided in the Appendix below). | |||||
"Derivative Works" shall mean any work, whether in Source or Object | |||||
form, that is based on (or derived from) the Work and for which the | |||||
editorial revisions, annotations, elaborations, or other modifications | |||||
represent, as a whole, an original work of authorship. For the purposes | |||||
of this License, Derivative Works shall not include works that remain | |||||
separable from, or merely link (or bind by name) to the interfaces of, | |||||
the Work and Derivative Works thereof. | |||||
"Contribution" shall mean any work of authorship, including | |||||
the original version of the Work and any modifications or additions | |||||
to that Work or Derivative Works thereof, that is intentionally | |||||
submitted to Licensor for inclusion in the Work by the copyright owner | |||||
or by an individual or Legal Entity authorized to submit on behalf of | |||||
the copyright owner. For the purposes of this definition, "submitted" | |||||
means any form of electronic, verbal, or written communication sent | |||||
to the Licensor or its representatives, including but not limited to | |||||
communication on electronic mailing lists, source code control systems, | |||||
and issue tracking systems that are managed by, or on behalf of, the | |||||
Licensor for the purpose of discussing and improving the Work, but | |||||
excluding communication that is conspicuously marked or otherwise | |||||
designated in writing by the copyright owner as "Not a Contribution." | |||||
"Contributor" shall mean Licensor and any individual or Legal Entity | |||||
on behalf of whom a Contribution has been received by Licensor and | |||||
subsequently incorporated within the Work. | |||||
2. Grant of Copyright License. Subject to the terms and conditions of | |||||
this License, each Contributor hereby grants to You a perpetual, | |||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||||
copyright license to reproduce, prepare Derivative Works of, | |||||
publicly display, publicly perform, sublicense, and distribute the | |||||
Work and such Derivative Works in Source or Object form. | |||||
3. Grant of Patent License. Subject to the terms and conditions of | |||||
this License, each Contributor hereby grants to You a perpetual, | |||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||||
(except as stated in this section) patent license to make, have made, | |||||
use, offer to sell, sell, import, and otherwise transfer the Work, | |||||
where such license applies only to those patent claims licensable | |||||
by such Contributor that are necessarily infringed by their | |||||
Contribution(s) alone or by combination of their Contribution(s) | |||||
with the Work to which such Contribution(s) was submitted. If You | |||||
institute patent litigation against any entity (including a | |||||
cross-claim or counterclaim in a lawsuit) alleging that the Work | |||||
or a Contribution incorporated within the Work constitutes direct | |||||
or contributory patent infringement, then any patent licenses | |||||
granted to You under this License for that Work shall terminate | |||||
as of the date such litigation is filed. | |||||
4. Redistribution. You may reproduce and distribute copies of the | |||||
Work or Derivative Works thereof in any medium, with or without | |||||
modifications, and in Source or Object form, provided that You | |||||
meet the following conditions: | |||||
(a) You must give any other recipients of the Work or | |||||
Derivative Works a copy of this License; and | |||||
(b) You must cause any modified files to carry prominent notices | |||||
stating that You changed the files; and | |||||
(c) You must retain, in the Source form of any Derivative Works | |||||
that You distribute, all copyright, patent, trademark, and | |||||
attribution notices from the Source form of the Work, | |||||
excluding those notices that do not pertain to any part of | |||||
the Derivative Works; and | |||||
(d) If the Work includes a "NOTICE" text file as part of its | |||||
distribution, then any Derivative Works that You distribute must | |||||
include a readable copy of the attribution notices contained | |||||
within such NOTICE file, excluding those notices that do not | |||||
pertain to any part of the Derivative Works, in at least one | |||||
of the following places: within a NOTICE text file distributed | |||||
as part of the Derivative Works; within the Source form or | |||||
documentation, if provided along with the Derivative Works; or, | |||||
within a display generated by the Derivative Works, if and | |||||
wherever such third-party notices normally appear. The contents | |||||
of the NOTICE file are for informational purposes only and | |||||
do not modify the License. You may add Your own attribution | |||||
notices within Derivative Works that You distribute, alongside | |||||
or as an addendum to the NOTICE text from the Work, provided | |||||
that such additional attribution notices cannot be construed | |||||
as modifying the License. | |||||
You may add Your own copyright statement to Your modifications and | |||||
may provide additional or different license terms and conditions | |||||
for use, reproduction, or distribution of Your modifications, or | |||||
for any such Derivative Works as a whole, provided Your use, | |||||
reproduction, and distribution of the Work otherwise complies with | |||||
the conditions stated in this License. | |||||
5. Submission of Contributions. Unless You explicitly state otherwise, | |||||
any Contribution intentionally submitted for inclusion in the Work | |||||
by You to the Licensor shall be under the terms and conditions of | |||||
this License, without any additional terms or conditions. | |||||
Notwithstanding the above, nothing herein shall supersede or modify | |||||
the terms of any separate license agreement you may have executed | |||||
with Licensor regarding such Contributions. | |||||
6. Trademarks. This License does not grant permission to use the trade | |||||
names, trademarks, service marks, or product names of the Licensor, | |||||
except as required for reasonable and customary use in describing the | |||||
origin of the Work and reproducing the content of the NOTICE file. | |||||
7. Disclaimer of Warranty. Unless required by applicable law or | |||||
agreed to in writing, Licensor provides the Work (and each | |||||
Contributor provides its Contributions) on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |||||
implied, including, without limitation, any warranties or conditions | |||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | |||||
PARTICULAR PURPOSE. You are solely responsible for determining the | |||||
appropriateness of using or redistributing the Work and assume any | |||||
risks associated with Your exercise of permissions under this License. | |||||
8. Limitation of Liability. In no event and under no legal theory, | |||||
whether in tort (including negligence), contract, or otherwise, | |||||
unless required by applicable law (such as deliberate and grossly | |||||
negligent acts) or agreed to in writing, shall any Contributor be | |||||
liable to You for damages, including any direct, indirect, special, | |||||
incidental, or consequential damages of any character arising as a | |||||
result of this License or out of the use or inability to use the | |||||
Work (including but not limited to damages for loss of goodwill, | |||||
work stoppage, computer failure or malfunction, or any and all | |||||
other commercial damages or losses), even if such Contributor | |||||
has been advised of the possibility of such damages. | |||||
9. Accepting Warranty or Additional Liability. While redistributing | |||||
the Work or Derivative Works thereof, You may choose to offer, | |||||
and charge a fee for, acceptance of support, warranty, indemnity, | |||||
or other liability obligations and/or rights consistent with this | |||||
License. However, in accepting such obligations, You may act only | |||||
on Your own behalf and on Your sole responsibility, not on behalf | |||||
of any other Contributor, and only if You agree to indemnify, | |||||
defend, and hold each Contributor harmless for any liability | |||||
incurred by, or claims asserted against, such Contributor by reason | |||||
of your accepting any such warranty or additional liability. | |||||
END OF TERMS AND CONDITIONS | |||||
APPENDIX: How to apply the Apache License to your work. | |||||
To apply the Apache License to your work, attach the following | |||||
boilerplate notice, with the fields enclosed by brackets "[]" | |||||
replaced with your own identifying information. (Don't include | |||||
the brackets!) The text should be enclosed in the appropriate | |||||
comment syntax for the file format. We also recommend that a | |||||
file or class name and description of purpose be included on the | |||||
same "printed page" as the copyright notice for easier | |||||
identification within third-party archives. | |||||
Copyright [yyyy] [name of copyright owner] | |||||
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. |
This product includes software developed by | |||||
The Apache Software Foundation (http://www.apache.org/). |
package org.apache.fop.fo; | package org.apache.fop.fo; | ||||
import java.util.Iterator; | import java.util.Iterator; | ||||
import java.util.List; | |||||
import java.util.Map; | import java.util.Map; | ||||
import org.w3c.dom.DOMImplementation; | |||||
import org.xml.sax.Locator; | |||||
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
import org.apache.commons.logging.LogFactory; | import org.apache.commons.logging.LogFactory; | ||||
import org.apache.xmlgraphics.util.Service; | |||||
import org.apache.fop.apps.FOPException; | import org.apache.fop.apps.FOPException; | ||||
import org.apache.fop.apps.FopFactory; | import org.apache.fop.apps.FopFactory; | ||||
import org.apache.fop.fo.ElementMapping.Maker; | import org.apache.fop.fo.ElementMapping.Maker; | ||||
import org.apache.fop.util.Service; | |||||
import org.w3c.dom.DOMImplementation; | |||||
import org.xml.sax.Locator; | |||||
/** | /** | ||||
* This class keeps track of all configured ElementMapping implementations which are responsible | * This class keeps track of all configured ElementMapping implementations which are responsible | ||||
Iterator providers = Service.providers(ElementMapping.class); | Iterator providers = Service.providers(ElementMapping.class); | ||||
if (providers != null) { | if (providers != null) { | ||||
while (providers.hasNext()) { | while (providers.hasNext()) { | ||||
String str = (String)providers.next(); | |||||
ElementMapping mapping = (ElementMapping)providers.next(); | |||||
try { | try { | ||||
addElementMapping(str); | |||||
addElementMapping(mapping); | |||||
} catch (IllegalArgumentException e) { | } catch (IllegalArgumentException e) { | ||||
log.warn("Error while adding element mapping", e); | log.warn("Error while adding element mapping", e); | ||||
} | } |
/* | /* | ||||
* Copyright 2004-2005 The Apache Software Foundation | |||||
* Copyright 2004-2006 The Apache Software Foundation | |||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | ||||
package org.apache.fop.image; | package org.apache.fop.image; | ||||
import java.awt.color.ColorSpace; | |||||
import java.awt.color.ICC_Profile; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import org.apache.batik.ext.awt.image.codec.PNGRed; | |||||
import org.apache.batik.ext.awt.image.codec.PNGDecodeParam; | |||||
import org.apache.batik.ext.awt.image.codec.SeekableStream; | |||||
import org.apache.batik.ext.awt.image.rendered.CachableRed; | |||||
import org.apache.xmlgraphics.image.codec.png.PNGRed; | |||||
import org.apache.xmlgraphics.image.codec.png.PNGDecodeParam; | |||||
import org.apache.xmlgraphics.image.codec.util.SeekableStream; | |||||
import org.apache.xmlgraphics.image.rendered.CachableRed; | |||||
import org.apache.commons.io.IOUtils; | import org.apache.commons.io.IOUtils; | ||||
import org.apache.fop.util.CMYKColorSpace; | |||||
/** | /** | ||||
* FopImage object using PNG | * FopImage object using PNG | ||||
* @see AbstractFopImage | * @see AbstractFopImage | ||||
* @see FopImage | * @see FopImage | ||||
*/ | */ | ||||
public class PNGImage extends BatikImage { | |||||
public class PNGImage extends XmlGraphicsCommonsImage { | |||||
/** | /** | ||||
* Constructs a new PNGImage instance. | * Constructs a new PNGImage instance. | ||||
} | } | ||||
/** | /** | ||||
* @see org.apache.fop.image.BatikImage#decodeImage(org.apache.batik.ext.awt.image.codec.SeekableStream) | |||||
* @see org.apache.fop.image.XmlGraphicsCommonsImage#decodeImage( | |||||
* org.apache.xmlgraphics.image.codec.util.SeekableStream) | |||||
*/ | */ | ||||
protected CachableRed decodeImage(SeekableStream stream) throws IOException { | protected CachableRed decodeImage(SeekableStream stream) throws IOException { | ||||
PNGDecodeParam param = new PNGDecodeParam(); | PNGDecodeParam param = new PNGDecodeParam(); |
/* | /* | ||||
* Copyright 2004-2005 The Apache Software Foundation | |||||
* Copyright 2004-2006 The Apache Software Foundation | |||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | ||||
import java.awt.color.ColorSpace; | import java.awt.color.ColorSpace; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import org.apache.batik.ext.awt.image.codec.SeekableStream; | |||||
import org.apache.batik.ext.awt.image.codec.tiff.TIFFDirectory; | |||||
import org.apache.batik.ext.awt.image.codec.tiff.TIFFField; | |||||
import org.apache.batik.ext.awt.image.codec.tiff.TIFFImageDecoder; | |||||
import org.apache.batik.ext.awt.image.rendered.CachableRed; | |||||
import org.apache.xmlgraphics.image.codec.util.SeekableStream; | |||||
import org.apache.xmlgraphics.image.codec.tiff.TIFFDirectory; | |||||
import org.apache.xmlgraphics.image.codec.tiff.TIFFField; | |||||
import org.apache.xmlgraphics.image.codec.tiff.TIFFImageDecoder; | |||||
import org.apache.xmlgraphics.image.rendered.CachableRed; | |||||
import org.apache.commons.io.IOUtils; | import org.apache.commons.io.IOUtils; | ||||
/** | /** | ||||
* TIFF implementation using the Batik codecs. | * TIFF implementation using the Batik codecs. | ||||
*/ | */ | ||||
public class TIFFImage extends BatikImage { | |||||
public class TIFFImage extends XmlGraphicsCommonsImage { | |||||
private int compression = 0; | private int compression = 0; | ||||
private int stripCount = 0; | private int stripCount = 0; | ||||
return stripCount; | return stripCount; | ||||
} | } | ||||
/** @see org.apache.fop.image.BatikImage */ | |||||
/** | |||||
* @see org.apache.fop.image.XmlGraphicsCommonsImage#decodeImage( | |||||
* org.apache.xmlgraphics.image.codec.util.SeekableStream) | |||||
*/ | |||||
protected CachableRed decodeImage(SeekableStream stream) throws IOException { | protected CachableRed decodeImage(SeekableStream stream) throws IOException { | ||||
org.apache.batik.ext.awt.image.codec.tiff.TIFFImage img | |||||
= new org.apache.batik.ext.awt.image.codec.tiff.TIFFImage | |||||
org.apache.xmlgraphics.image.codec.tiff.TIFFImage img | |||||
= new org.apache.xmlgraphics.image.codec.tiff.TIFFImage | |||||
(stream, null, 0); | (stream, null, 0); | ||||
TIFFDirectory dir = (TIFFDirectory)img.getProperty("tiff_directory"); | TIFFDirectory dir = (TIFFDirectory)img.getProperty("tiff_directory"); | ||||
TIFFField fld = dir.getField(TIFFImageDecoder.TIFF_RESOLUTION_UNIT); | TIFFField fld = dir.getField(TIFFImageDecoder.TIFF_RESOLUTION_UNIT); |
/* | /* | ||||
* Copyright 2004-2005 The Apache Software Foundation | |||||
* Copyright 2004-2006 The Apache Software Foundation | |||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | ||||
import java.awt.Transparency; | import java.awt.Transparency; | ||||
import java.awt.image.ColorModel; | import java.awt.image.ColorModel; | ||||
import java.awt.image.IndexColorModel; | import java.awt.image.IndexColorModel; | ||||
import java.awt.image.RenderedImage; | |||||
import java.awt.image.WritableRaster; | import java.awt.image.WritableRaster; | ||||
import java.awt.image.BufferedImage; | import java.awt.image.BufferedImage; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import org.apache.batik.ext.awt.image.codec.SeekableStream; | |||||
import org.apache.batik.ext.awt.image.codec.MemoryCacheSeekableStream; | |||||
import org.apache.batik.ext.awt.image.codec.FileCacheSeekableStream; | |||||
import org.apache.batik.ext.awt.image.rendered.Any2sRGBRed; | |||||
import org.apache.batik.ext.awt.image.rendered.CachableRed; | |||||
import org.apache.xmlgraphics.image.GraphicsUtil; | |||||
import org.apache.xmlgraphics.image.codec.util.SeekableStream; | |||||
import org.apache.xmlgraphics.image.codec.util.MemoryCacheSeekableStream; | |||||
import org.apache.xmlgraphics.image.codec.util.FileCacheSeekableStream; | |||||
import org.apache.xmlgraphics.image.rendered.CachableRed; | |||||
import org.apache.commons.io.IOUtils; | import org.apache.commons.io.IOUtils; | ||||
/** | /** | ||||
* FopImage object using TIFF | |||||
* @author Eric SCHAEFFER | |||||
* Abstract FopImage implementation which uses the internal codecs from XML Graphics Commons. | |||||
* @see AbstractFopImage | * @see AbstractFopImage | ||||
* @see FopImage | * @see FopImage | ||||
*/ | */ | ||||
public abstract class BatikImage extends AbstractFopImage { | |||||
public abstract class XmlGraphicsCommonsImage extends AbstractFopImage { | |||||
private byte[] softMask = null; | private byte[] softMask = null; | ||||
* Constructs a new BatikImage instance. | * Constructs a new BatikImage instance. | ||||
* @param imgReader basic metadata for the image | * @param imgReader basic metadata for the image | ||||
*/ | */ | ||||
public BatikImage(FopImage.ImageInfo imgReader) { | |||||
public XmlGraphicsCommonsImage(FopImage.ImageInfo imgReader) { | |||||
super(imgReader); | super(imgReader); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
cr = new Any2sRGBRed(cr); | |||||
cr = GraphicsUtil.convertTosRGB(cr); | |||||
} | } | ||||
// Get our current ColorModel | // Get our current ColorModel | ||||
this.bitmaps = new byte[this.width * this.height * 3]; | this.bitmaps = new byte[this.width * this.height * 3]; | ||||
WritableRaster wr = (WritableRaster)cr.getData(); | |||||
BufferedImage bi = new BufferedImage | |||||
(cm, wr.createWritableTranslatedChild(0, 0), | |||||
cm.isAlphaPremultiplied(), null); | |||||
int [] tmpMap = new int[this.width]; | |||||
int idx = 0; | |||||
int sfIdx = 0; | |||||
for (int y = 0; y < this.height; y++) { | |||||
tmpMap = bi.getRGB(0, y, this.width, 1, tmpMap, 0, this.width); | |||||
if (softMask != null) { | |||||
for (int x = 0; x < this.width; x++) { | |||||
int pix = tmpMap[x]; | |||||
this.softMask[sfIdx++] = (byte)(pix >>> 24); | |||||
this.bitmaps[idx++] = (byte)((pix >>> 16) & 0xFF); | |||||
this.bitmaps[idx++] = (byte)((pix >>> 8) & 0xFF); | |||||
this.bitmaps[idx++] = (byte)((pix) & 0xFF); | |||||
} | |||||
} else { | |||||
for (int x = 0; x < this.width; x++) { | |||||
int pix = tmpMap[x]; | |||||
this.bitmaps[idx++] = (byte)((pix >> 16) & 0xFF); | |||||
this.bitmaps[idx++] = (byte)((pix >> 8) & 0xFF); | |||||
this.bitmaps[idx++] = (byte)((pix) & 0xFF); | |||||
} | |||||
} | |||||
} | |||||
constructBitmaps(cr, this.bitmaps, this.softMask); | |||||
} catch (Exception ex) { | } catch (Exception ex) { | ||||
log.error("Error while loading image (Batik): " + ex.getMessage(), ex); | log.error("Error while loading image (Batik): " + ex.getMessage(), ex); | ||||
} finally { | } finally { | ||||
} | } | ||||
} | } | ||||
} | } | ||||
}; | |||||
private static void constructBitmaps(RenderedImage red, byte[] bitmaps, byte[] softMask) { | |||||
WritableRaster wr = (WritableRaster)red.getData(); | |||||
ColorModel cm = red.getColorModel(); | |||||
BufferedImage bi = new BufferedImage | |||||
(cm, wr.createWritableTranslatedChild(0, 0), | |||||
cm.isAlphaPremultiplied(), null); | |||||
int width = red.getWidth(); | |||||
int height = red.getHeight(); | |||||
int [] tmpMap = new int[width]; | |||||
int idx = 0; | |||||
int sfIdx = 0; | |||||
for (int y = 0; y < height; y++) { | |||||
tmpMap = bi.getRGB(0, y, width, 1, tmpMap, 0, width); | |||||
if (softMask != null) { | |||||
for (int x = 0; x < width; x++) { | |||||
int pix = tmpMap[x]; | |||||
softMask[sfIdx++] = (byte)(pix >>> 24); | |||||
bitmaps[idx++] = (byte)((pix >>> 16) & 0xFF); | |||||
bitmaps[idx++] = (byte)((pix >>> 8) & 0xFF); | |||||
bitmaps[idx++] = (byte)((pix) & 0xFF); | |||||
} | |||||
} else { | |||||
for (int x = 0; x < width; x++) { | |||||
int pix = tmpMap[x]; | |||||
bitmaps[idx++] = (byte)((pix >> 16) & 0xFF); | |||||
bitmaps[idx++] = (byte)((pix >> 8) & 0xFF); | |||||
bitmaps[idx++] = (byte)((pix) & 0xFF); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import org.apache.fop.util.ASCII85OutputStream; | |||||
import org.apache.xmlgraphics.util.io.ASCII85OutputStream; | |||||
/** | /** | ||||
* PDF Filter for ASCII85. | * PDF Filter for ASCII85. |
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import org.apache.fop.util.ASCIIHexOutputStream; | |||||
import org.apache.xmlgraphics.util.io.ASCIIHexOutputStream; | |||||
/** | /** | ||||
* ASCII Hex filter for PDF streams. | * ASCII Hex filter for PDF streams. |
package org.apache.fop.pdf; | package org.apache.fop.pdf; | ||||
import org.apache.fop.util.FlateEncodeOutputStream; | |||||
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import org.apache.xmlgraphics.util.io.FlateEncodeOutputStream; | |||||
/** | /** | ||||
* A filter to deflate a stream. | * A filter to deflate a stream. | ||||
* <p> | * <p> |
import java.util.List; | import java.util.List; | ||||
import java.util.Map; | import java.util.Map; | ||||
//Avalon | |||||
import org.apache.avalon.framework.configuration.Configuration; | import org.apache.avalon.framework.configuration.Configuration; | ||||
import org.apache.avalon.framework.configuration.ConfigurationException; | import org.apache.avalon.framework.configuration.ConfigurationException; | ||||
import org.apache.avalon.framework.container.ContainerUtil; | import org.apache.avalon.framework.container.ContainerUtil; | ||||
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
import org.apache.commons.logging.LogFactory; | import org.apache.commons.logging.LogFactory; | ||||
//FOP | |||||
import org.apache.xmlgraphics.util.Service; | |||||
import org.apache.fop.apps.FOPException; | import org.apache.fop.apps.FOPException; | ||||
import org.apache.fop.apps.FOUserAgent; | import org.apache.fop.apps.FOUserAgent; | ||||
import org.apache.fop.area.AreaTreeHandler; | import org.apache.fop.area.AreaTreeHandler; | ||||
import org.apache.fop.fo.FOEventHandler; | import org.apache.fop.fo.FOEventHandler; | ||||
import org.apache.fop.util.Service; | |||||
/** | /** | ||||
* Factory for FOEventHandlers and Renderers. | * Factory for FOEventHandlers and Renderers. | ||||
= Service.providers(Renderer.class); | = Service.providers(Renderer.class); | ||||
if (providers != null) { | if (providers != null) { | ||||
while (providers.hasNext()) { | while (providers.hasNext()) { | ||||
String str = (String)providers.next(); | |||||
AbstractRendererMaker maker = (AbstractRendererMaker)providers.next(); | |||||
try { | try { | ||||
if (log.isDebugEnabled()) { | if (log.isDebugEnabled()) { | ||||
log.debug("Dynamically adding maker for Renderer: " + str); | |||||
log.debug("Dynamically adding maker for Renderer: " | |||||
+ maker.getClass().getName()); | |||||
} | } | ||||
addRendererMaker(str); | |||||
addRendererMaker(maker); | |||||
} catch (IllegalArgumentException e) { | } catch (IllegalArgumentException e) { | ||||
log.error("Error while adding maker for Renderer", e); | log.error("Error while adding maker for Renderer", e); | ||||
} | } | ||||
= Service.providers(FOEventHandler.class); | = Service.providers(FOEventHandler.class); | ||||
if (providers != null) { | if (providers != null) { | ||||
while (providers.hasNext()) { | while (providers.hasNext()) { | ||||
String str = (String)providers.next(); | |||||
AbstractFOEventHandlerMaker maker = (AbstractFOEventHandlerMaker)providers.next(); | |||||
try { | try { | ||||
if (log.isDebugEnabled()) { | if (log.isDebugEnabled()) { | ||||
log.debug("Dynamically adding maker for FOEventHandler: " + str); | |||||
log.debug("Dynamically adding maker for FOEventHandler: " | |||||
+ maker.getClass().getName()); | |||||
} | } | ||||
addFOEventHandlerMaker(str); | |||||
addFOEventHandlerMaker(maker); | |||||
} catch (IllegalArgumentException e) { | } catch (IllegalArgumentException e) { | ||||
log.error("Error while adding maker for FOEventHandler", e); | log.error("Error while adding maker for FOEventHandler", e); | ||||
} | } |
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
import org.apache.commons.logging.LogFactory; | import org.apache.commons.logging.LogFactory; | ||||
import org.apache.fop.util.Service; | |||||
import org.apache.xmlgraphics.util.Service; | |||||
/** | /** | ||||
* This class holds references to various XML handlers used by FOP. It also | * This class holds references to various XML handlers used by FOP. It also | ||||
Iterator providers = Service.providers(XMLHandler.class); | Iterator providers = Service.providers(XMLHandler.class); | ||||
if (providers != null) { | if (providers != null) { | ||||
while (providers.hasNext()) { | while (providers.hasNext()) { | ||||
String str = (String)providers.next(); | |||||
XMLHandler handler = (XMLHandler)providers.next(); | |||||
try { | try { | ||||
if (log.isDebugEnabled()) { | if (log.isDebugEnabled()) { | ||||
log.debug("Dynamically adding XMLHandler: " + str); | |||||
log.debug("Dynamically adding XMLHandler: " + handler.getClass().getName()); | |||||
} | } | ||||
addXMLHandler(str); | |||||
addXMLHandler(handler); | |||||
} catch (IllegalArgumentException e) { | } catch (IllegalArgumentException e) { | ||||
log.error("Error while adding XMLHandler", e); | log.error("Error while adding XMLHandler", e); | ||||
} | } |
/* | /* | ||||
* Copyright 2005 The Apache Software Foundation. | |||||
* Copyright 2005-2006 The Apache Software Foundation. | |||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import org.apache.batik.ext.awt.image.codec.PNGEncodeParam; | |||||
import org.apache.batik.ext.awt.image.codec.PNGImageEncoder; | |||||
import org.apache.xmlgraphics.image.writer.ImageWriter; | |||||
import org.apache.xmlgraphics.image.writer.ImageWriterParams; | |||||
import org.apache.xmlgraphics.image.writer.ImageWriterRegistry; | |||||
import org.apache.commons.io.IOUtils; | import org.apache.commons.io.IOUtils; | ||||
import org.apache.fop.apps.FOPException; | import org.apache.fop.apps.FOPException; | ||||
import org.apache.fop.apps.MimeConstants; | import org.apache.fop.apps.MimeConstants; | ||||
import org.apache.fop.area.PageViewport; | import org.apache.fop.area.PageViewport; | ||||
/** The output directory where images are to be written */ | /** The output directory where images are to be written */ | ||||
private File outputDir; | private File outputDir; | ||||
/** The PNGEncodeParam for the image */ | |||||
private PNGEncodeParam renderParams; | |||||
/** The OutputStream for the first Image */ | /** The OutputStream for the first Image */ | ||||
private OutputStream firstOutputStream; | private OutputStream firstOutputStream; | ||||
// Encode this image | // Encode this image | ||||
log.debug("Encoding page " + (i + 1)); | log.debug("Encoding page " + (i + 1)); | ||||
renderParams = PNGEncodeParam.getDefaultEncodeParam(image); | |||||
// Set resolution | |||||
float pixSzMM = userAgent.getTargetPixelUnitToMillimeter(); | |||||
// num Pixs in 1 Meter | |||||
int numPix = (int)((1000 / pixSzMM) + 0.5); | |||||
renderParams.setPhysicalDimension(numPix, numPix, 1); // 1 means 'pix/meter' | |||||
ImageWriterParams params = new ImageWriterParams(); | |||||
params.setResolution(Math.round(userAgent.getTargetResolution())); | |||||
// Encode PNG image | // Encode PNG image | ||||
PNGImageEncoder encoder = new PNGImageEncoder(os, renderParams); | |||||
encoder.encode(image); | |||||
ImageWriter writer = ImageWriterRegistry.getInstance().getWriterFor(getMimeType()); | |||||
log.debug("Writing image using " + writer.getClass().getName()); | |||||
writer.writeImage(image, os, params); | |||||
} finally { | } finally { | ||||
//Only close self-created OutputStreams | //Only close self-created OutputStreams | ||||
if (os != firstOutputStream) { | if (os != firstOutputStream) { |
/* | /* | ||||
* Copyright 2005 The Apache Software Foundation. | |||||
* Copyright 2005-2006 The Apache Software Foundation. | |||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import org.apache.batik.ext.awt.image.codec.PNGEncodeParam; | |||||
import org.apache.batik.ext.awt.image.codec.PNGImageEncoder; | |||||
import org.apache.xmlgraphics.image.codec.png.PNGEncodeParam; | |||||
import org.apache.xmlgraphics.image.codec.png.PNGImageEncoder; | |||||
import org.apache.commons.io.IOUtils; | import org.apache.commons.io.IOUtils; | ||||
import org.apache.fop.apps.FOPException; | import org.apache.fop.apps.FOPException; | ||||
import org.apache.fop.area.PageViewport; | import org.apache.fop.area.PageViewport; | ||||
import org.apache.fop.render.java2d.Java2DRenderer; | import org.apache.fop.render.java2d.Java2DRenderer; |
/* | /* | ||||
* Copyright 1999-2005 The Apache Software Foundation. | |||||
* Copyright 1999-2006 The Apache Software Foundation. | |||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | ||||
import org.apache.avalon.framework.configuration.Configuration; | import org.apache.avalon.framework.configuration.Configuration; | ||||
import org.apache.avalon.framework.configuration.ConfigurationException; | import org.apache.avalon.framework.configuration.ConfigurationException; | ||||
import org.apache.batik.ext.awt.image.GraphicsUtil; | |||||
import org.apache.batik.ext.awt.image.codec.tiff.TIFFEncodeParam; | |||||
import org.apache.batik.ext.awt.image.codec.tiff.TIFFField; | |||||
import org.apache.batik.ext.awt.image.codec.tiff.TIFFImageDecoder; | |||||
import org.apache.batik.ext.awt.image.codec.tiff.TIFFImageEncoder; | |||||
import org.apache.batik.ext.awt.image.rendered.FormatRed; | |||||
import org.apache.xmlgraphics.image.GraphicsUtil; | |||||
import org.apache.xmlgraphics.image.codec.tiff.TIFFEncodeParam; | |||||
import org.apache.xmlgraphics.image.codec.tiff.TIFFField; | |||||
import org.apache.xmlgraphics.image.codec.tiff.TIFFImageDecoder; | |||||
import org.apache.xmlgraphics.image.codec.tiff.TIFFImageEncoder; | |||||
import org.apache.xmlgraphics.image.rendered.FormatRed; | |||||
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
import org.apache.fop.apps.FOPException; | import org.apache.fop.apps.FOPException; | ||||
import org.apache.fop.apps.MimeConstants; | import org.apache.fop.apps.MimeConstants; |
/* | |||||
* Copyright 1999-2006 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.render.ps; | |||||
//Java | |||||
import java.awt.Color; | |||||
import java.awt.Shape; | |||||
import java.awt.geom.AffineTransform; | |||||
import java.io.OutputStream; | |||||
import java.io.IOException; | |||||
//FOP | |||||
import org.apache.fop.fonts.FontInfo; | |||||
import org.apache.fop.fonts.FontSetup; | |||||
/** | |||||
* This class is a wrapper for the <tt>PSGraphics2D</tt> that | |||||
* is used to create a full document around the PostScript rendering from | |||||
* <tt>PSGraphics2D</tt>. | |||||
* | |||||
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | |||||
* @version $Id$ | |||||
* @see org.apache.fop.render.ps.PSGraphics2D | |||||
*/ | |||||
public abstract class AbstractPSDocumentGraphics2D extends PSGraphics2D { | |||||
protected static final Integer ZERO = new Integer(0); | |||||
protected int width; | |||||
protected int height; | |||||
protected float viewportWidth; | |||||
protected float viewportHeight; | |||||
protected int pagecount; | |||||
protected boolean pagePending; | |||||
protected Shape initialClip; | |||||
protected AffineTransform initialTransform; | |||||
/** | |||||
* Create a new AbstractPSDocumentGraphics2D. | |||||
* This is used to create a new PostScript document, the height, | |||||
* width and output stream can be setup later. | |||||
* For use by the transcoder which needs font information | |||||
* for the bridge before the document size is known. | |||||
* The resulting document is written to the stream after rendering. | |||||
* | |||||
* @param textAsShapes set this to true so that text will be rendered | |||||
* using curves and not the font. | |||||
*/ | |||||
AbstractPSDocumentGraphics2D(boolean textAsShapes) { | |||||
super(textAsShapes); | |||||
if (!textAsShapes) { | |||||
fontInfo = new FontInfo(); | |||||
FontSetup.setup(fontInfo, null, null); | |||||
} | |||||
} | |||||
/** | |||||
* Setup the document. | |||||
* @param stream the output stream to write the document | |||||
* @param width the width of the page | |||||
* @param height the height of the page | |||||
* @throws IOException an io exception if there is a problem | |||||
* writing to the output stream | |||||
*/ | |||||
public void setupDocument(OutputStream stream, int width, int height) throws IOException { | |||||
this.width = width; | |||||
this.height = height; | |||||
this.pagecount = 0; | |||||
this.pagePending = false; | |||||
//Setup for PostScript generation | |||||
setPSGenerator(new PSGenerator(stream)); | |||||
writeFileHeader(); | |||||
} | |||||
protected abstract void writeFileHeader() throws IOException; | |||||
/** | |||||
* Create a new AbstractPSDocumentGraphics2D. | |||||
* This is used to create a new PostScript document of the given height | |||||
* and width. | |||||
* The resulting document is written to the stream after rendering. | |||||
* | |||||
* @param textAsShapes set this to true so that text will be rendered | |||||
* using curves and not the font. | |||||
* @param stream the stream that the final document should be written to. | |||||
* @param width the width of the document | |||||
* @param height the height of the document | |||||
* @throws IOException an io exception if there is a problem | |||||
* writing to the output stream | |||||
*/ | |||||
public AbstractPSDocumentGraphics2D(boolean textAsShapes, OutputStream stream, | |||||
int width, int height) throws IOException { | |||||
this(textAsShapes); | |||||
setupDocument(stream, width, height); | |||||
} | |||||
/** | |||||
* Set the dimensions of the SVG document that will be drawn. | |||||
* This is useful if the dimensions of the SVG document are different | |||||
* from the PostScript document that is to be created. | |||||
* The result is scaled so that the SVG fits correctly inside the | |||||
* PostScript document. | |||||
* @param w the width of the page | |||||
* @param h the height of the page | |||||
* @throws IOException in case of an I/O problem | |||||
*/ | |||||
public void setSVGDimension(float w, float h) throws IOException { | |||||
this.viewportWidth = w; | |||||
this.viewportHeight = h; | |||||
/* | |||||
if (w != this.width || h != this.height) { | |||||
gen.concatMatrix(width / w, 0, 0, height / h, 0, 0); | |||||
}*/ | |||||
} | |||||
/** | |||||
* Set the background of the PostScript document. | |||||
* This is used to set the background for the PostScript document | |||||
* Rather than leaving it as the default white. | |||||
* @param col the background colour to fill | |||||
*/ | |||||
public void setBackgroundColor(Color col) { | |||||
/**(todo) Implement this */ | |||||
/* | |||||
Color c = col; | |||||
PDFColor currentColour = new PDFColor(c.getRed(), c.getGreen(), c.getBlue()); | |||||
currentStream.write("q\n"); | |||||
currentStream.write(currentColour.getColorSpaceOut(true)); | |||||
currentStream.write("0 0 " + width + " " + height + " re\n"); | |||||
currentStream.write("f\n"); | |||||
currentStream.write("Q\n"); | |||||
*/ | |||||
} | |||||
public int getPageCount() { | |||||
return this.pagecount; | |||||
} | |||||
public void nextPage() throws IOException { | |||||
closePage(); | |||||
} | |||||
protected void closePage() throws IOException { | |||||
if (!this.pagePending) { | |||||
return; //ignore | |||||
} | |||||
//Finish page | |||||
writePageTrailer(); | |||||
this.pagePending = false; | |||||
} | |||||
/** | |||||
* Writes the page header for a page. | |||||
* @throws IOException In case an I/O error occurs | |||||
*/ | |||||
protected abstract void writePageHeader() throws IOException; | |||||
/** | |||||
* Writes the page trailer for a page. | |||||
* @throws IOException In case an I/O error occurs | |||||
*/ | |||||
protected abstract void writePageTrailer() throws IOException; | |||||
/** {@inheritDoc} */ | |||||
protected void preparePainting() { | |||||
if (this.pagePending) { | |||||
return; | |||||
} | |||||
try { | |||||
startPage(); | |||||
} catch (IOException ioe) { | |||||
handleIOException(ioe); | |||||
} | |||||
} | |||||
protected void startPage() throws IOException { | |||||
if (this.pagePending) { | |||||
throw new IllegalStateException("Close page first before starting another"); | |||||
} | |||||
//Start page | |||||
this.pagecount++; | |||||
if (this.initialTransform == null) { | |||||
//Save initial transformation matrix | |||||
this.initialTransform = getTransform(); | |||||
this.initialClip = getClip(); | |||||
} else { | |||||
//Reset transformation matrix | |||||
setTransform(this.initialTransform); | |||||
setClip(this.initialClip); | |||||
} | |||||
writePageHeader(); | |||||
if ((this.viewportWidth != this.width | |||||
|| this.viewportHeight != this.height) | |||||
&& (this.viewportWidth > 0) && (this.viewportHeight > 0)){ | |||||
gen.concatMatrix(this.width / this.viewportWidth, 0, | |||||
0, -1 * (this.height / this.viewportHeight), | |||||
0, this.height); | |||||
} else { | |||||
gen.concatMatrix(1, 0, 0, -1, 0, this.height); | |||||
} | |||||
gen.writeDSCComment(DSCConstants.END_PAGE_SETUP); | |||||
this.pagePending = true; | |||||
} | |||||
/** | |||||
* The rendering process has finished. | |||||
* This should be called after the rendering has completed as there is | |||||
* no other indication it is complete. | |||||
* This will then write the results to the output stream. | |||||
* @throws IOException an io exception if there is a problem | |||||
* writing to the output stream | |||||
*/ | |||||
public void finish() throws IOException { | |||||
if (this.pagePending) { | |||||
closePage(); | |||||
} | |||||
//Finish document | |||||
gen.writeDSCComment(DSCConstants.TRAILER); | |||||
gen.writeDSCComment(DSCConstants.PAGES, new Integer(this.pagecount)); | |||||
gen.writeDSCComment(DSCConstants.EOF); | |||||
gen.flush(); | |||||
} | |||||
/** | |||||
* This constructor supports the create method | |||||
* @param g the PostScript document graphics to make a copy of | |||||
*/ | |||||
public AbstractPSDocumentGraphics2D(AbstractPSDocumentGraphics2D g) { | |||||
super(g); | |||||
} | |||||
} | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import org.apache.avalon.framework.configuration.Configuration; | import org.apache.avalon.framework.configuration.Configuration; | ||||
import org.apache.avalon.framework.container.ContainerUtil; | |||||
import org.apache.batik.bridge.BridgeContext; | import org.apache.batik.bridge.BridgeContext; | ||||
import org.apache.batik.bridge.UnitProcessor; | import org.apache.batik.bridge.UnitProcessor; | ||||
import org.apache.batik.transcoder.TranscoderException; | import org.apache.batik.transcoder.TranscoderException; | ||||
import org.apache.batik.transcoder.image.ImageTranscoder; | import org.apache.batik.transcoder.image.ImageTranscoder; | ||||
import org.apache.fop.fonts.FontInfo; | |||||
import org.apache.fop.fonts.FontSetup; | |||||
import org.apache.fop.svg.AbstractFOPTranscoder; | import org.apache.fop.svg.AbstractFOPTranscoder; | ||||
import org.apache.xmlgraphics.java2d.ps.AbstractPSDocumentGraphics2D; | |||||
import org.apache.xmlgraphics.java2d.ps.TextHandler; | |||||
import org.w3c.dom.Document; | import org.w3c.dom.Document; | ||||
import org.w3c.dom.svg.SVGLength; | import org.w3c.dom.svg.SVGLength; | ||||
* millimeter conversion factor. | * millimeter conversion factor. | ||||
* | * | ||||
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | ||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | |||||
* @version $Id$ | * @version $Id$ | ||||
*/ | */ | ||||
public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { | public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { | ||||
throws TranscoderException { | throws TranscoderException { | ||||
graphics = createDocumentGraphics2D(); | graphics = createDocumentGraphics2D(); | ||||
try { | |||||
if (this.cfg != null) { | |||||
ContainerUtil.configure(graphics, this.cfg); | |||||
} | |||||
ContainerUtil.initialize(graphics); | |||||
} catch (Exception e) { | |||||
throw new TranscoderException( | |||||
"Error while setting up PDFDocumentGraphics2D", e); | |||||
if (!isTextStroked()) { | |||||
FontInfo fontInfo = new FontInfo(); | |||||
//TODO Do custom font configuration here somewhere/somehow | |||||
FontSetup.setup(fontInfo, null, null); | |||||
graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo)); | |||||
} | } | ||||
super.transcode(document, uri, output); | super.transcode(document, uri, output); | ||||
UnitProcessor.HORIZONTAL_LENGTH, uctx); | UnitProcessor.HORIZONTAL_LENGTH, uctx); | ||||
int h = (int)(heightInPt + 0.5); | int h = (int)(heightInPt + 0.5); | ||||
getLogger().trace("document size: " + w + "pt x " + h + "pt"); | getLogger().trace("document size: " + w + "pt x " + h + "pt"); | ||||
try { | try { | ||||
graphics.setupDocument(output.getOutputStream(), w, h); | graphics.setupDocument(output.getOutputStream(), w, h); | ||||
graphics.setSVGDimension(width, height); | |||||
graphics.setViewportDimension(width, height); | |||||
if (hints.containsKey(ImageTranscoder.KEY_BACKGROUND_COLOR)) { | if (hints.containsKey(ImageTranscoder.KEY_BACKGROUND_COLOR)) { | ||||
graphics.setBackgroundColor | graphics.setBackgroundColor | ||||
((Color)hints.get(ImageTranscoder.KEY_BACKGROUND_COLOR)); | ((Color)hints.get(ImageTranscoder.KEY_BACKGROUND_COLOR)); | ||||
} | } | ||||
graphics.setGraphicContext | graphics.setGraphicContext | ||||
(new org.apache.batik.ext.awt.g2d.GraphicContext()); | |||||
(new org.apache.xmlgraphics.java2d.GraphicContext()); | |||||
graphics.setTransform(curTxf); | graphics.setTransform(curTxf); | ||||
this.root.paint(graphics); | this.root.paint(graphics); | ||||
throw new TranscoderException(ex); | throw new TranscoderException(ex); | ||||
} | } | ||||
} | } | ||||
protected BridgeContext createBridgeContext() { | |||||
/*boolean stroke = true; | |||||
/** @return true if text should be stroked rather than painted using text operators */ | |||||
protected boolean isTextStroked() { | |||||
boolean stroke = false; | |||||
if (hints.containsKey(KEY_STROKE_TEXT)) { | if (hints.containsKey(KEY_STROKE_TEXT)) { | ||||
stroke = ((Boolean)hints.get(KEY_STROKE_TEXT)).booleanValue(); | stroke = ((Boolean)hints.get(KEY_STROKE_TEXT)).booleanValue(); | ||||
}*/ | |||||
} | |||||
return stroke; | |||||
} | |||||
/** @see org.apache.batik.transcoder.SVGAbstractTranscoder#createBridgeContext() */ | |||||
protected BridgeContext createBridgeContext() { | |||||
BridgeContext ctx = new BridgeContext(userAgent); | BridgeContext ctx = new BridgeContext(userAgent); | ||||
PSTextPainter textPainter = new PSTextPainter(graphics.getFontInfo()); | |||||
ctx.setTextPainter(textPainter); | |||||
ctx.putBridge(new PSTextElementBridge(textPainter)); | |||||
if (!isTextStroked()) { | |||||
TextHandler handler = graphics.getCustomTextHandler(); | |||||
if (handler instanceof NativeTextHandler) { | |||||
NativeTextHandler nativeTextHandler = (NativeTextHandler)handler; | |||||
PSTextPainter textPainter = new PSTextPainter(nativeTextHandler); | |||||
ctx.setTextPainter(textPainter); | |||||
ctx.putBridge(new PSTextElementBridge(textPainter)); | |||||
} | |||||
} | |||||
//ctx.putBridge(new PSImageElementBridge()); | //ctx.putBridge(new PSImageElementBridge()); | ||||
return ctx; | return ctx; |
/* | |||||
* 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.render.ps; | |||||
/** | |||||
* This class defines constants with Strings for the DSC specification. | |||||
* | |||||
* @author <a href="mailto:fop-dev@xmlgraphics.apache.org">Apache FOP Development Team</a> | |||||
* @version $Id: DSCConstants.java,v 1.2 2003/03/07 09:46:30 jeremias Exp $ | |||||
*/ | |||||
public class DSCConstants { | |||||
// ----==== General Header Comments ====---- | |||||
/** Lead-in for a DSC-conformant PostScript file */ | |||||
public static final String PS_ADOBE_30 = "%!PS-Adobe-3.0"; | |||||
/** Lead-in for an EPS file */ | |||||
public static final String EPSF_30 = "EPSF-3.0"; | |||||
/** Bounding box for the document */ | |||||
public static final String BBOX = "BoundingBox"; | |||||
/** High-resolution bounding box for the document */ | |||||
public static final String HIRES_BBOX = "HiResBoundingBox"; | |||||
/** Copyright information associated with the document or resource */ | |||||
public static final String COPYRIGHT = "Copyright"; | |||||
/** Creator of the document */ | |||||
public static final String CREATOR = "Creator"; | |||||
/** Date and time when the document was created */ | |||||
public static final String CREATION_DATE = "CreationDate"; | |||||
/** Type of data */ | |||||
public static final String DOCUMENT_DATA = "BoundingBox"; | |||||
/** Use for inidicating an emulator being invoked in the document */ | |||||
public static final String EMULATION = "Emulation"; | |||||
/** Explicit end of comments */ | |||||
public static final String END_COMMENTS = "EndComments"; | |||||
/** Required PostScript Level 1 extension for this document */ | |||||
public static final String EXTENSIONS = "Extensions"; | |||||
/** Indicates who is this document printed for */ | |||||
public static final String FOR = "For"; | |||||
/** Indicates the PostScript language level used in the document */ | |||||
public static final String LANGUAGE_LEVEL = "LanguageLevel"; | |||||
/** Indicates the orientation of the document */ | |||||
public static final String ORIENTATION = "Orientation"; | |||||
/** Number of pages in the document */ | |||||
public static final String PAGES = "Pages"; | |||||
/** Indicates the order of the pages */ | |||||
public static final String PAGE_ORDER = "PageOrder"; | |||||
/** Indicates how the document should be routed back to its owner */ | |||||
public static final String ROUTING = "Routing"; | |||||
/** Title of the document */ | |||||
public static final String TITLE = "Title"; | |||||
/** Version of the document */ | |||||
public static final String VERSION = "Version"; | |||||
// ----==== General Body Comments ====---- | |||||
/** Indicates a continued line */ | |||||
public static final String NEXT_LINE = "+ "; | |||||
//Skipping BeginBinary/EndBinary. They are deprecated. | |||||
/** Indicates the start of a data section*/ | |||||
public static final String BEGIN_DATA = "BeginData"; | |||||
/** Indicates the end of a data section*/ | |||||
public static final String END_DATA = "EndData"; | |||||
/** Indicates the start of the defaults section */ | |||||
public static final String BEGIN_DEFAULTS = "BeginDefaults"; | |||||
/** Indicates the end of the defaults section */ | |||||
public static final String END_DEFAULTS = "EndDefaults"; | |||||
/** Indicates the start of a non-PostScript section */ | |||||
public static final String BEGIN_EMULATION = "BeginEmulation"; | |||||
/** Indicates the end of a non-PostScript section */ | |||||
public static final String END_EMULATION = "EndEmulation"; | |||||
/** Indicates the start of a preview section (EPS only)*/ | |||||
public static final String BEGIN_PREVIEW = "BeginPreview"; | |||||
/** Indicates the end of a preview section (EPS only)*/ | |||||
public static final String END_PREVIEW = "EndPreview"; | |||||
/** Indicates the start of the prolog */ | |||||
public static final String BEGIN_PROLOG = "BeginProlog"; | |||||
/** Indicates the end of the prolog */ | |||||
public static final String END_PROLOG = "EndProlog"; | |||||
/** Indicates the start of the document setup */ | |||||
public static final String BEGIN_SETUP = "BeginSetup"; | |||||
/** Indicates the end of the document setup */ | |||||
public static final String END_SETUP = "EndSetup"; | |||||
// ----==== General Page Comments ====---- | |||||
/** Indicates the start of a graphic object */ | |||||
public static final String BEGIN_OBJECT = "BeginObject"; | |||||
/** Indicates the end of a graphic object */ | |||||
public static final String END_OBJECT = "EndObject"; | |||||
/** Indicates the start of the page setup section */ | |||||
public static final String BEGIN_PAGE_SETUP = "BeginPageSetup"; | |||||
/** Indicates the end of the page setup section */ | |||||
public static final String END_PAGE_SETUP = "EndPageSetup"; | |||||
/** Indicates a page number */ | |||||
public static final String PAGE = "Page"; | |||||
/** Bounding box for a page */ | |||||
public static final String PAGE_BBOX = "PageBoundingBox"; | |||||
/** High-resolution bounding box for a page */ | |||||
public static final String PAGE_HIRES_BBOX = "PageHiResBoundingBox"; | |||||
/** Bounding box for a page */ | |||||
public static final String PAGE_ORIENTATION = "PageOrientation"; | |||||
// ----==== General Trailer Comments ====---- | |||||
/** Indicates the start of the page trailer */ | |||||
public static final String PAGE_TRAILER = "PageTrailer"; | |||||
/** Indicates the start of the document trailer */ | |||||
public static final String TRAILER = "Trailer"; | |||||
/** Indicates the end of a page (NON-STANDARD!) */ | |||||
public static final String END_PAGE = "EndPage"; | |||||
/** Indicates the end of the document */ | |||||
public static final String EOF = "EOF"; | |||||
// ----==== Requirements Conventions ====---- | |||||
/**@todo Add the missing comments */ | |||||
/** | |||||
* This comment indicates all types of paper media (paper sizes, weight, color) | |||||
* this document requires. | |||||
*/ | |||||
public static final String DOCUMENT_MEDIA = "DocumentMedia"; | |||||
/** This comment provides a list of resources the document needs */ | |||||
public static final String DOCUMENT_NEEDED_RESOURCES = "DocumentNeededResources"; | |||||
/** This comment provides a list of resources the document includes */ | |||||
public static final String DOCUMENT_SUPPLIED_RESOURCES = "DocumentSuppliedResources"; | |||||
//Skipping %%DocumentPrinterRequired | |||||
//Skipping %%DocumentNeededFiles -> deprecated | |||||
//Skipping %%DocumentSuppliedFiles -> deprecated | |||||
//Skipping %%DocumentFonts -> deprecated | |||||
//Skipping %%DocumentNeededFonts -> deprecated | |||||
//Skipping %%DocumentSuppliedFonts -> deprecated | |||||
//Skipping %%DocumentNeededProcSets -> deprecated | |||||
//Skipping %%DocumentSuppliedProcSets -> deprecated | |||||
//Skipping %%OperatorIntervention | |||||
//Skipping %%OperatorMessage | |||||
//Skipping %%ProofMode | |||||
/** | |||||
* This comment describes document requirements, such as duplex printing, | |||||
* hole punching, collating, or other physical document processing needs. | |||||
*/ | |||||
public static final String REQUIREMENTS = "Requirements"; | |||||
//Skipping %%VMlocation | |||||
//Skipping %%VMusage | |||||
// ----==== Requirement Body Comments ====---- | |||||
/** Indicates the start of an embedded document */ | |||||
public static final String BEGIN_DOCUMENT = "BeginDocument"; | |||||
/** Indicates the end of an embedded document */ | |||||
public static final String END_DOCUMENT = "EndDocument"; | |||||
/** Indicates a referenced embedded document */ | |||||
public static final String INCLUDE_DOCUMENT = "IncludeDocument"; | |||||
/** Indicates the start of a PPD feature */ | |||||
public static final String BEGIN_FEATURE = "BeginFeature"; | |||||
/** Indicates the end of a PPD feature */ | |||||
public static final String END_FEATURE = "EndFeature"; | |||||
/** Indicates a referenced a PPD feature */ | |||||
public static final String INCLUDE_FEATURE = "IncludeFeature"; | |||||
//Skipping BeginFile/EndFile/IncludeFile. They are deprecated. | |||||
//Skipping BeginFont/EndFont/IncludeFont. They are deprecated. | |||||
//Skipping BeginProcSet/EndProcSet/IncludeProcSet. They are deprecated. | |||||
/** Indicates the start of a resource (font, file, procset) */ | |||||
public static final String BEGIN_RESOURCE = "BeginResource"; | |||||
/** Indicates the end of a resource (font, file, procset) */ | |||||
public static final String END_RESOURCE = "EndResource"; | |||||
/** Indicates a referenced a resource (font, file, procset) */ | |||||
public static final String INCLUDE_RESOURCE = "IncludeResource"; | |||||
// ----==== Requirement Page Comments ====---- | |||||
//Skipping %%PageFonts -> deprecated | |||||
//Skipping %%PageFiles -> deprecated | |||||
/** Indicates that the paper attributes denoted by medianame are invoked on this page. */ | |||||
public static final String PAGE_MEDIA = "PageMedia"; | |||||
/** | |||||
* This is the page-level invocation of a combination of the options listed in | |||||
* the %%Requirements: comment. | |||||
*/ | |||||
public static final String PAGE_REQUIREMENTS = "PageRequirements"; | |||||
/** | |||||
* This comment indicates the names and values of all resources that are needed | |||||
* or supplied on the present page. | |||||
*/ | |||||
public static final String PAGE_RESOURCES = "PageResources"; | |||||
} |
/* | |||||
* Copyright 2003-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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.render.ps; | |||||
import java.io.IOException; | |||||
import org.apache.fop.Version; | |||||
/** | |||||
* This class is a wrapper for the <tt>AbstractPSDocumentGraphics2D</tt> that | |||||
* is used to create EPS (Encapsulated PostScript) files instead of PS file. | |||||
* | |||||
* @version $Id$ | |||||
* @see org.apache.fop.render.ps.PSGraphics2D | |||||
* @see org.apache.fop.render.ps.AbstractPSDocumentGraphics2D | |||||
*/ | |||||
public class EPSDocumentGraphics2D extends AbstractPSDocumentGraphics2D { | |||||
/** | |||||
* Create a new EPSDocumentGraphics2D. | |||||
* This is used to create a new EPS document, the height, | |||||
* width and output stream can be setup later. | |||||
* For use by the transcoder which needs font information | |||||
* for the bridge before the document size is known. | |||||
* The resulting document is written to the stream after rendering. | |||||
* | |||||
* @param textAsShapes set this to true so that text will be rendered | |||||
* using curves and not the font. | |||||
*/ | |||||
public EPSDocumentGraphics2D(boolean textAsShapes) { | |||||
super(textAsShapes); | |||||
} | |||||
protected void writeFileHeader() throws IOException { | |||||
final Long pagewidth = new Long(this.width); | |||||
final Long pageheight = new Long(this.height); | |||||
//PostScript Header | |||||
gen.writeln(DSCConstants.PS_ADOBE_30 + " " + DSCConstants.EPSF_30); | |||||
gen.writeDSCComment(DSCConstants.CREATOR, | |||||
new String[] {"Apache FOP " + Version.getVersion() | |||||
+ ": EPS Transcoder for SVG"}); | |||||
gen.writeDSCComment(DSCConstants.CREATION_DATE, | |||||
new Object[] {new java.util.Date()}); | |||||
gen.writeDSCComment(DSCConstants.PAGES, new Integer(0)); | |||||
gen.writeDSCComment(DSCConstants.BBOX, new Object[] | |||||
{ZERO, ZERO, pagewidth, pageheight}); | |||||
gen.writeDSCComment(DSCConstants.LANGUAGE_LEVEL, new Integer(gen.getPSLevel())); | |||||
gen.writeDSCComment(DSCConstants.END_COMMENTS); | |||||
//Prolog | |||||
gen.writeDSCComment(DSCConstants.BEGIN_PROLOG); | |||||
PSProcSets.writeFOPStdProcSet(gen); | |||||
PSProcSets.writeFOPEPSProcSet(gen); | |||||
if (fontInfo != null) { | |||||
PSFontUtils.writeFontDict(gen, fontInfo); | |||||
} | |||||
gen.writeDSCComment(DSCConstants.END_PROLOG); | |||||
} | |||||
protected void writePageHeader() throws IOException { | |||||
Integer pageNumber = new Integer(this.pagecount); | |||||
gen.writeDSCComment(DSCConstants.PAGE, new Object[] | |||||
{pageNumber.toString(), pageNumber}); | |||||
gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] | |||||
{ZERO, ZERO, new Integer(width), new Integer(height)}); | |||||
gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP); | |||||
if (fontInfo != null) { | |||||
gen.writeln("FOPFonts begin"); | |||||
} | |||||
} | |||||
protected void writePageTrailer() throws IOException { | |||||
gen.writeDSCComment(DSCConstants.PAGE_TRAILER); | |||||
gen.writeDSCComment(DSCConstants.END_PAGE); | |||||
} | |||||
} |
/* | /* | ||||
* Copyright 1999-2004 The Apache Software Foundation. | |||||
* Copyright 1999-2004,2006 The Apache Software Foundation. | |||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | ||||
package org.apache.fop.render.ps; | package org.apache.fop.render.ps; | ||||
import org.apache.xmlgraphics.java2d.ps.AbstractPSDocumentGraphics2D; | |||||
import org.apache.xmlgraphics.java2d.ps.EPSDocumentGraphics2D; | |||||
/** | /** | ||||
* This class enables to transcode an input to a EPS document. | * This class enables to transcode an input to a EPS document. | ||||
* | * | ||||
* millimeter conversion factor. | * millimeter conversion factor. | ||||
* | * | ||||
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | ||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | |||||
* @version $Id$ | * @version $Id$ | ||||
*/ | */ | ||||
public class EPSTranscoder extends AbstractPSTranscoder { | public class EPSTranscoder extends AbstractPSTranscoder { | ||||
super(); | super(); | ||||
} | } | ||||
/** @see AbstractPSTranscoder#createDocumentGraphics2D() */ | |||||
protected AbstractPSDocumentGraphics2D createDocumentGraphics2D() { | protected AbstractPSDocumentGraphics2D createDocumentGraphics2D() { | ||||
return new EPSDocumentGraphics2D(false); | return new EPSDocumentGraphics2D(false); | ||||
} | } |
/* | |||||
* Copyright 1999-2006 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.render.ps; | |||||
import java.awt.Shape; | |||||
import java.awt.geom.AffineTransform; | |||||
import java.io.IOException; | |||||
import org.apache.fop.fonts.Font; | |||||
import org.apache.fop.fonts.FontInfo; | |||||
import org.apache.fop.fonts.FontSetup; | |||||
import org.apache.fop.fonts.FontTriplet; | |||||
import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; | |||||
import org.apache.xmlgraphics.java2d.ps.TextHandler; | |||||
import org.apache.xmlgraphics.ps.PSGenerator; | |||||
/** | |||||
* Specialized TextHandler implementation that the PSGraphics2D class delegates to to paint text | |||||
* using PostScript text operations. | |||||
*/ | |||||
public class NativeTextHandler implements TextHandler { | |||||
private PSGraphics2D g2d; | |||||
/** FontInfo containing all available fonts */ | |||||
protected FontInfo fontInfo; | |||||
/** Currently valid Font */ | |||||
protected Font font; | |||||
/** Overriding FontState */ | |||||
protected Font overrideFont = null; | |||||
/** the current (internal) font name */ | |||||
protected String currentFontName; | |||||
/** the current font size in millipoints */ | |||||
protected int currentFontSize; | |||||
/** | |||||
* Main constructor. | |||||
* @param g2d the PSGraphics2D instance this instances is used by | |||||
* @param fontInfo the FontInfo object with all available fonts | |||||
*/ | |||||
public NativeTextHandler(PSGraphics2D g2d, FontInfo fontInfo) { | |||||
this.g2d = g2d; | |||||
if (fontInfo != null) { | |||||
this.fontInfo = fontInfo; | |||||
} else { | |||||
setupFontInfo(); | |||||
} | |||||
} | |||||
private void setupFontInfo() { | |||||
//Sets up a FontInfo with default fonts | |||||
fontInfo = new FontInfo(); | |||||
FontSetup.setup(fontInfo, null, null); | |||||
} | |||||
/** | |||||
* Return the font information associated with this object | |||||
* @return the FontInfo object | |||||
*/ | |||||
public FontInfo getFontInfo() { | |||||
return fontInfo; | |||||
} | |||||
private PSGenerator getPSGenerator() { | |||||
return this.g2d.getPSGenerator(); | |||||
} | |||||
/** @see org.apache.xmlgraphics.java2d.ps.TextHandler#writeSetup() */ | |||||
public void writeSetup() throws IOException { | |||||
if (fontInfo != null) { | |||||
PSFontUtils.writeFontDict(getPSGenerator(), fontInfo); | |||||
} | |||||
} | |||||
/** @see org.apache.xmlgraphics.java2d.ps.TextHandler#writePageSetup() */ | |||||
public void writePageSetup() throws IOException { | |||||
if (fontInfo != null) { | |||||
getPSGenerator().writeln("FOPFonts begin"); | |||||
} | |||||
} | |||||
/** | |||||
* Draw a string to the PostScript document. The text is painted using | |||||
* text operations. | |||||
* @see org.apache.xmlgraphics.java2d.ps.TextHandler#drawString(java.lang.String, float, float) | |||||
*/ | |||||
public void drawString(String s, float x, float y) throws IOException { | |||||
g2d.preparePainting(); | |||||
if (this.overrideFont == null) { | |||||
java.awt.Font awtFont = g2d.getFont(); | |||||
this.font = createFont(awtFont); | |||||
} else { | |||||
this.font = this.overrideFont; | |||||
this.overrideFont = null; | |||||
} | |||||
//Color and Font state | |||||
g2d.establishColor(g2d.getColor()); | |||||
establishCurrentFont(); | |||||
PSGenerator gen = getPSGenerator(); | |||||
gen.saveGraphicsState(); | |||||
//Clip | |||||
Shape imclip = g2d.getClip(); | |||||
g2d.writeClip(imclip); | |||||
//Prepare correct transformation | |||||
AffineTransform trans = g2d.getTransform(); | |||||
gen.concatMatrix(trans); | |||||
gen.writeln(gen.formatDouble(x) + " " | |||||
+ gen.formatDouble(y) + " moveto "); | |||||
gen.writeln("1 -1 scale"); | |||||
StringBuffer sb = new StringBuffer("("); | |||||
escapeText(s, sb); | |||||
sb.append(") t "); | |||||
gen.writeln(sb.toString()); | |||||
gen.restoreGraphicsState(); | |||||
} | |||||
private void escapeText(final String text, StringBuffer target) { | |||||
final int l = text.length(); | |||||
for (int i = 0; i < l; i++) { | |||||
final char ch = text.charAt(i); | |||||
final char mch = this.font.mapChar(ch); | |||||
PSGenerator.escapeChar(mch, target); | |||||
} | |||||
} | |||||
private Font createFont(java.awt.Font f) { | |||||
String fontFamily = f.getFamily(); | |||||
if (fontFamily.equals("sanserif")) { | |||||
fontFamily = "sans-serif"; | |||||
} | |||||
int fontSize = 1000 * f.getSize(); | |||||
String style = f.isItalic() ? "italic" : "normal"; | |||||
int weight = f.isBold() ? Font.BOLD : Font.NORMAL; | |||||
FontTriplet triplet = fontInfo.findAdjustWeight(fontFamily, style, weight); | |||||
if (triplet == null) { | |||||
triplet = fontInfo.findAdjustWeight("sans-serif", style, weight); | |||||
} | |||||
return fontInfo.getFontInstance(triplet, fontSize); | |||||
} | |||||
private void establishCurrentFont() throws IOException { | |||||
if ((currentFontName != this.font.getFontName()) | |||||
|| (currentFontSize != this.font.getFontSize())) { | |||||
PSGenerator gen = getPSGenerator(); | |||||
gen.writeln(this.font.getFontName() + " " | |||||
+ gen.formatDouble(font.getFontSize() / 1000f) + " F"); | |||||
currentFontName = this.font.getFontName(); | |||||
currentFontSize = this.font.getFontSize(); | |||||
} | |||||
} | |||||
/** | |||||
* Sets the overriding font. | |||||
* @param override Overriding Font to set | |||||
*/ | |||||
public void setOverrideFont(Font override) { | |||||
this.overrideFont = override; | |||||
} | |||||
} |
/* | |||||
* Copyright 1999-2006 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.render.ps; | |||||
//Java | |||||
import java.awt.Graphics; | |||||
import java.io.OutputStream; | |||||
import java.io.IOException; | |||||
//FOP | |||||
import org.apache.fop.Version; | |||||
import org.apache.fop.fonts.FontInfo; | |||||
import org.apache.fop.fonts.FontSetup; | |||||
/** | |||||
* This class is a wrapper for the <tt>PSGraphics2D</tt> that | |||||
* is used to create a full document around the PostScript rendering from | |||||
* <tt>PSGraphics2D</tt>. | |||||
* | |||||
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | |||||
* @version $Id$ | |||||
* @see org.apache.fop.render.ps.PSGraphics2D | |||||
*/ | |||||
public class PSDocumentGraphics2D extends AbstractPSDocumentGraphics2D { | |||||
/** | |||||
* Create a new AbstractPSDocumentGraphics2D. | |||||
* This is used to create a new PostScript document, the height, | |||||
* width and output stream can be setup later. | |||||
* For use by the transcoder which needs font information | |||||
* for the bridge before the document size is known. | |||||
* The resulting document is written to the stream after rendering. | |||||
* | |||||
* @param textAsShapes set this to true so that text will be rendered | |||||
* using curves and not the font. | |||||
*/ | |||||
PSDocumentGraphics2D(boolean textAsShapes) { | |||||
super(textAsShapes); | |||||
} | |||||
/** | |||||
* Create a new AbstractPSDocumentGraphics2D. | |||||
* This is used to create a new PostScript document of the given height | |||||
* and width. | |||||
* The resulting document is written to the stream after rendering. | |||||
* | |||||
* @param textAsShapes set this to true so that text will be rendered | |||||
* using curves and not the font. | |||||
* @param stream the stream that the final document should be written to. | |||||
* @param width the width of the document | |||||
* @param height the height of the document | |||||
* @throws IOException an io exception if there is a problem | |||||
* writing to the output stream | |||||
*/ | |||||
public PSDocumentGraphics2D(boolean textAsShapes, OutputStream stream, | |||||
int width, int height) throws IOException { | |||||
this(textAsShapes); | |||||
setupDocument(stream, width, height); | |||||
} | |||||
public void nextPage() throws IOException { | |||||
closePage(); | |||||
} | |||||
protected void writeFileHeader() throws IOException { | |||||
final Long pagewidth = new Long(this.width); | |||||
final Long pageheight = new Long(this.height); | |||||
//PostScript Header | |||||
gen.writeln(DSCConstants.PS_ADOBE_30); | |||||
gen.writeDSCComment(DSCConstants.CREATOR, | |||||
new String[] {"Apache FOP " + Version.getVersion() | |||||
+ ": PostScript Transcoder for SVG"}); | |||||
gen.writeDSCComment(DSCConstants.CREATION_DATE, | |||||
new Object[] {new java.util.Date()}); | |||||
gen.writeDSCComment(DSCConstants.PAGES, PSGenerator.ATEND); | |||||
gen.writeDSCComment(DSCConstants.BBOX, new Object[] | |||||
{ZERO, ZERO, pagewidth, pageheight}); | |||||
gen.writeDSCComment(DSCConstants.END_COMMENTS); | |||||
//Defaults | |||||
gen.writeDSCComment(DSCConstants.BEGIN_DEFAULTS); | |||||
gen.writeDSCComment(DSCConstants.END_DEFAULTS); | |||||
//Prolog | |||||
gen.writeDSCComment(DSCConstants.BEGIN_PROLOG); | |||||
gen.writeDSCComment(DSCConstants.END_PROLOG); | |||||
//Setup | |||||
gen.writeDSCComment(DSCConstants.BEGIN_SETUP); | |||||
PSProcSets.writeFOPStdProcSet(gen); | |||||
PSProcSets.writeFOPEPSProcSet(gen); | |||||
if (fontInfo != null) { | |||||
PSFontUtils.writeFontDict(gen, fontInfo); | |||||
} | |||||
gen.writeDSCComment(DSCConstants.END_SETUP); | |||||
} | |||||
protected void writePageHeader() throws IOException { | |||||
Integer pageNumber = new Integer(this.pagecount); | |||||
gen.writeDSCComment(DSCConstants.PAGE, new Object[] | |||||
{pageNumber.toString(), pageNumber}); | |||||
gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] | |||||
{ZERO, ZERO, new Integer(width), new Integer(height)}); | |||||
gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP); | |||||
gen.writeln("<<"); | |||||
gen.writeln("/PageSize [" + width + " " + height + "]"); | |||||
gen.writeln("/ImagingBBox null"); | |||||
gen.writeln(">> setpagedevice"); | |||||
if (fontInfo != null) { | |||||
gen.writeln("FOPFonts begin"); | |||||
} | |||||
} | |||||
protected void writePageTrailer() throws IOException { | |||||
gen.writeln("showpage"); | |||||
gen.writeDSCComment(DSCConstants.PAGE_TRAILER); | |||||
gen.writeDSCComment(DSCConstants.END_PAGE); | |||||
} | |||||
/** | |||||
* This constructor supports the create method | |||||
* @param g the PostScript document graphics to make a copy of | |||||
*/ | |||||
public PSDocumentGraphics2D(PSDocumentGraphics2D g) { | |||||
super(g); | |||||
} | |||||
/** | |||||
* Creates a new <code>Graphics</code> object that is | |||||
* a copy of this <code>Graphics</code> object. | |||||
* @return a new graphics context that is a copy of | |||||
* this graphics context. | |||||
*/ | |||||
public Graphics create() { | |||||
return new PSDocumentGraphics2D(this); | |||||
} | |||||
} | |||||
package org.apache.fop.render.ps; | package org.apache.fop.render.ps; | ||||
import java.io.BufferedReader; | |||||
import java.io.FileNotFoundException; | import java.io.FileNotFoundException; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.InputStream; | import java.io.InputStream; | ||||
import javax.xml.transform.Source; | import javax.xml.transform.Source; | ||||
import javax.xml.transform.stream.StreamSource; | import javax.xml.transform.stream.StreamSource; | ||||
import org.apache.commons.io.EndianUtils; | |||||
import org.apache.commons.io.IOUtils; | |||||
import org.apache.fop.fonts.CustomFont; | import org.apache.fop.fonts.CustomFont; | ||||
import org.apache.fop.fonts.Font; | import org.apache.fop.fonts.Font; | ||||
import org.apache.fop.fonts.FontInfo; | import org.apache.fop.fonts.FontInfo; | ||||
import org.apache.fop.fonts.FontType; | import org.apache.fop.fonts.FontType; | ||||
import org.apache.fop.fonts.Glyphs; | |||||
import org.apache.fop.fonts.LazyFont; | import org.apache.fop.fonts.LazyFont; | ||||
import org.apache.fop.fonts.Typeface; | import org.apache.fop.fonts.Typeface; | ||||
import org.apache.fop.util.ASCIIHexOutputStream; | |||||
import org.apache.fop.util.SubInputStream; | |||||
import org.apache.xmlgraphics.ps.DSCConstants; | |||||
import org.apache.xmlgraphics.ps.PSGenerator; | |||||
import org.apache.xmlgraphics.ps.PSResource; | |||||
/** | /** | ||||
* Utility code for font handling in PostScript. | * Utility code for font handling in PostScript. | ||||
*/ | */ | ||||
public class PSFontUtils { | |||||
public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils { | |||||
/** | /** | ||||
* Generates the PostScript code for the font dictionary. | * Generates the PostScript code for the font dictionary. | ||||
return fontResources; | return fontResources; | ||||
} | } | ||||
/** | |||||
* This method reads a Type 1 font from a stream and embeds it into a PostScript stream. | |||||
* Note: Only the IBM PC Format as described in section 3.3 of the Adobe Technical Note #5040 | |||||
* is supported. | |||||
* @param gen The PostScript generator | |||||
* @param in the InputStream from which to read the Type 1 font | |||||
* @throws IOException in case an I/O problem occurs | |||||
*/ | |||||
private static void embedType1Font(PSGenerator gen, InputStream in) throws IOException { | |||||
boolean finished = false; | |||||
while (!finished) { | |||||
int segIndicator = in.read(); | |||||
if (segIndicator < 0) { | |||||
throw new IOException("Unexpected end-of-file while reading segment indicator"); | |||||
} else if (segIndicator != 128) { | |||||
throw new IOException("Expected ASCII 128, found: " + segIndicator); | |||||
} | |||||
int segType = in.read(); | |||||
if (segType < 0) { | |||||
throw new IOException("Unexpected end-of-file while reading segment type"); | |||||
} | |||||
int dataSegLen = 0; | |||||
switch (segType) { | |||||
case 1: //ASCII | |||||
dataSegLen = EndianUtils.readSwappedInteger(in); | |||||
BufferedReader reader = new BufferedReader( | |||||
new java.io.InputStreamReader( | |||||
new SubInputStream(in, dataSegLen), "US-ASCII")); | |||||
String line; | |||||
while ((line = reader.readLine()) != null) { | |||||
gen.writeln(line); | |||||
} | |||||
break; | |||||
case 2: //binary | |||||
dataSegLen = EndianUtils.readSwappedInteger(in); | |||||
SubInputStream sin = new SubInputStream(in, dataSegLen); | |||||
ASCIIHexOutputStream hexOut = new ASCIIHexOutputStream(gen.getOutputStream()); | |||||
IOUtils.copy(sin, hexOut); | |||||
gen.newLine(); | |||||
break; | |||||
case 3: //EOF | |||||
finished = true; | |||||
break; | |||||
default: throw new IOException("Unsupported segment type: " + segType); | |||||
} | |||||
} | |||||
} | |||||
private static InputStream getInputStreamOnFont(PSGenerator gen, CustomFont font) | private static InputStream getInputStreamOnFont(PSGenerator gen, CustomFont font) | ||||
throws IOException { | throws IOException { | ||||
if (font.isEmbeddable()) { | if (font.isEmbeddable()) { | ||||
} | } | ||||
} | } | ||||
private static void defineWinAnsiEncoding(PSGenerator gen) throws IOException { | |||||
gen.writeln("/WinAnsiEncoding ["); | |||||
for (int i = 0; i < Glyphs.WINANSI_ENCODING.length; i++) { | |||||
if (i > 0) { | |||||
if ((i % 5) == 0) { | |||||
gen.newLine(); | |||||
} else { | |||||
gen.write(" "); | |||||
} | |||||
} | |||||
final char ch = Glyphs.WINANSI_ENCODING[i]; | |||||
final String glyphname = Glyphs.charToGlyphName(ch); | |||||
if ("".equals(glyphname)) { | |||||
gen.write("/" + Glyphs.NOTDEF); | |||||
} else { | |||||
gen.write("/"); | |||||
gen.write(glyphname); | |||||
} | |||||
} | |||||
gen.newLine(); | |||||
gen.writeln("] def"); | |||||
} | |||||
} | } |
/* | |||||
* 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.render.ps; | |||||
import java.awt.Color; | |||||
import java.awt.geom.AffineTransform; | |||||
import java.io.OutputStream; | |||||
import java.io.IOException; | |||||
import java.text.DateFormat; | |||||
import java.text.DecimalFormat; | |||||
import java.text.DecimalFormatSymbols; | |||||
import java.util.Date; | |||||
import java.util.Iterator; | |||||
import java.util.Locale; | |||||
import java.util.Set; | |||||
import java.util.Stack; | |||||
import javax.xml.transform.Source; | |||||
/** | |||||
* This class is used to output PostScript code to an OutputStream. | |||||
* | |||||
* @author <a href="mailto:fop-dev@xmlgraphics.apache.org">Apache FOP Development Team</a> | |||||
* @version $Id$ | |||||
*/ | |||||
public class PSGenerator { | |||||
/** | |||||
* Indicator for the PostScript interpreter that the value is provided | |||||
* later in the document (mostly in the %%Trailer section). | |||||
*/ | |||||
public static final AtendIndicator ATEND = new AtendIndicator() { | |||||
}; | |||||
/** Line feed used by PostScript */ | |||||
public static final char LF = '\n'; | |||||
private OutputStream out; | |||||
private boolean commentsEnabled = true; | |||||
private Stack graphicsStateStack = new Stack(); | |||||
private PSState currentState; | |||||
//private DecimalFormat df3 = new DecimalFormat("0.000", new DecimalFormatSymbols(Locale.US)); | |||||
private DecimalFormat df3 = new DecimalFormat("0.###", new DecimalFormatSymbols(Locale.US)); | |||||
private DecimalFormat df5 = new DecimalFormat("0.#####", new DecimalFormatSymbols(Locale.US)); | |||||
private StringBuffer tempBuffer = new StringBuffer(256); | |||||
/** @see java.io.FilterOutputStream **/ | |||||
public PSGenerator(OutputStream out) { | |||||
this.out = out; | |||||
this.currentState = new PSState(); | |||||
//this.graphicsStateStack.push(this.currentState); | |||||
} | |||||
/** | |||||
* Returns the OutputStream the PSGenerator writes to. | |||||
* @return the OutputStream | |||||
*/ | |||||
public OutputStream getOutputStream() { | |||||
return this.out; | |||||
} | |||||
/** | |||||
* Returns the selected PostScript level. | |||||
* (Hardcoded to level 2 for the moment.) | |||||
* @return the PostScript level | |||||
*/ | |||||
public int getPSLevel() { | |||||
return 2; | |||||
} | |||||
/** | |||||
* Attempts to resolve the given URI. PSGenerator should be subclasses to provide more | |||||
* sophisticated URI resolution. | |||||
* @param uri URI to access | |||||
* @return A {@link javax.xml.transform.Source} object, or null if the URI | |||||
* cannot be resolved. | |||||
*/ | |||||
public Source resolveURI(String uri) { | |||||
return new javax.xml.transform.stream.StreamSource(uri); | |||||
} | |||||
/** | |||||
* Writes a newline character to the OutputStream. | |||||
* | |||||
* @throws IOException In case of an I/O problem | |||||
*/ | |||||
public final void newLine() throws IOException { | |||||
out.write(LF); | |||||
} | |||||
/** | |||||
* Formats a double value for PostScript output. | |||||
* | |||||
* @param value value to format | |||||
* @return the formatted value | |||||
*/ | |||||
public String formatDouble(double value) { | |||||
return df3.format(value); | |||||
} | |||||
/** | |||||
* Formats a double value for PostScript output (higher resolution). | |||||
* | |||||
* @param value value to format | |||||
* @return the formatted value | |||||
*/ | |||||
public String formatDouble5(double value) { | |||||
return df5.format(value); | |||||
} | |||||
/** | |||||
* Writes a PostScript command to the stream. | |||||
* | |||||
* @param cmd The PostScript code to be written. | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void write(String cmd) throws IOException { | |||||
/* @todo Check disabled until clarification. | |||||
if (cmd.length() > 255) { | |||||
throw new RuntimeException("PostScript command exceeded limit of 255 characters"); | |||||
} */ | |||||
out.write(cmd.getBytes("US-ASCII")); | |||||
} | |||||
/** | |||||
* Writes a PostScript command to the stream and ends the line. | |||||
* | |||||
* @param cmd The PostScript code to be written. | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void writeln(String cmd) throws IOException { | |||||
write(cmd); | |||||
newLine(); | |||||
} | |||||
/** | |||||
* Writes a comment to the stream and ends the line. Output of comments can | |||||
* be disabled to reduce the size of the generated file. | |||||
* | |||||
* @param comment comment to write | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void commentln(String comment) throws IOException { | |||||
if (this.commentsEnabled) { | |||||
writeln(comment); | |||||
} | |||||
} | |||||
/** | |||||
* Writes encoded data to the PostScript stream. | |||||
* | |||||
* @param cmd The encoded PostScript code to be written. | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void writeByteArr(byte[] cmd) throws IOException { | |||||
out.write(cmd); | |||||
newLine(); | |||||
} | |||||
/** | |||||
* Flushes the OutputStream. | |||||
* | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void flush() throws IOException { | |||||
out.flush(); | |||||
} | |||||
/** | |||||
* Escapes a character conforming to the rules established in the PostScript | |||||
* Language Reference (Search for "Literal Text Strings"). | |||||
* @param c character to escape | |||||
* @param target target StringBuffer to write the escaped character to | |||||
*/ | |||||
public static final void escapeChar(char c, StringBuffer target) { | |||||
if (c > 127) { | |||||
target.append("\\"); | |||||
target.append(Integer.toOctalString(c)); | |||||
} else { | |||||
switch (c) { | |||||
case '\n': | |||||
target.append("\\n"); | |||||
break; | |||||
case '\r': | |||||
target.append("\\r"); | |||||
break; | |||||
case '\t': | |||||
target.append("\\t"); | |||||
break; | |||||
case '\b': | |||||
target.append("\\b"); | |||||
break; | |||||
case '\f': | |||||
target.append("\\f"); | |||||
break; | |||||
case '\\': | |||||
target.append("\\\\"); | |||||
break; | |||||
case '(': | |||||
target.append("\\("); | |||||
break; | |||||
case ')': | |||||
target.append("\\)"); | |||||
break; | |||||
default: | |||||
target.append(c); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* Converts text by applying escaping rules established in the DSC specs. | |||||
* @param text Text to convert | |||||
* @return String The resulting String | |||||
*/ | |||||
public static final String convertStringToDSC(String text) { | |||||
return convertStringToDSC(text, false); | |||||
} | |||||
/** | |||||
* Converts text by applying escaping rules established in the DSC specs. | |||||
* @param text Text to convert | |||||
* @param forceParentheses Force the use of parentheses | |||||
* @return String The resulting String | |||||
*/ | |||||
public static final String convertStringToDSC(String text, | |||||
boolean forceParentheses) { | |||||
if ((text == null) || (text.length() == 0)) { | |||||
return "()"; | |||||
} else { | |||||
int initialSize = text.length(); | |||||
initialSize += initialSize / 2; | |||||
StringBuffer sb = new StringBuffer(initialSize); | |||||
if ((Long.getLong(text) != null) | |||||
|| (text.indexOf(' ') >= 0) | |||||
|| forceParentheses) { | |||||
sb.append('('); | |||||
for (int i = 0; i < text.length(); i++) { | |||||
final char c = text.charAt(i); | |||||
escapeChar(c, sb); | |||||
} | |||||
sb.append(')'); | |||||
return sb.toString(); | |||||
} else { | |||||
return text; | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* Writes a DSC comment to the output stream. | |||||
* @param name Name of the DSC comment | |||||
* @exception IOException In case of an I/O problem | |||||
* @see org.apache.fop.render.ps.DSCConstants | |||||
*/ | |||||
public void writeDSCComment(String name) throws IOException { | |||||
writeln("%%" + name); | |||||
} | |||||
/** | |||||
* Writes a DSC comment to the output stream. The parameter to the DSC | |||||
* comment can be any object. The object is converted to a String as | |||||
* necessary. | |||||
* @param name Name of the DSC comment | |||||
* @param param Single parameter to the DSC comment | |||||
* @exception IOException In case of an I/O problem | |||||
* @see org.apache.fop.render.ps.DSCConstants | |||||
*/ | |||||
public void writeDSCComment(String name, Object param) throws IOException { | |||||
writeDSCComment(name, new Object[] {param}); | |||||
} | |||||
/** | |||||
* Writes a DSC comment to the output stream. The parameters to the DSC | |||||
* comment can be any object. The objects are converted to Strings as | |||||
* necessary. Please see the source code to find out what parameters are | |||||
* currently supported. | |||||
* @param name Name of the DSC comment | |||||
* @param params Array of parameters to the DSC comment | |||||
* @exception IOException In case of an I/O problem | |||||
* @see org.apache.fop.render.ps.DSCConstants | |||||
*/ | |||||
public void writeDSCComment(String name, Object[] params) throws IOException { | |||||
tempBuffer.setLength(0); | |||||
tempBuffer.append("%%"); | |||||
tempBuffer.append(name); | |||||
if ((params != null) && (params.length > 0)) { | |||||
tempBuffer.append(": "); | |||||
for (int i = 0; i < params.length; i++) { | |||||
if (i > 0) { | |||||
tempBuffer.append(" "); | |||||
} | |||||
if (params[i] instanceof String) { | |||||
tempBuffer.append(convertStringToDSC((String)params[i])); | |||||
} else if (params[i] instanceof AtendIndicator) { | |||||
tempBuffer.append("(atend)"); | |||||
} else if (params[i] instanceof Double) { | |||||
tempBuffer.append(df3.format(params[i])); | |||||
} else if (params[i] instanceof Number) { | |||||
tempBuffer.append(params[i].toString()); | |||||
} else if (params[i] instanceof Date) { | |||||
DateFormat datef = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); | |||||
tempBuffer.append(convertStringToDSC(datef.format((Date)params[i]))); | |||||
} else if (params[i] instanceof PSResource) { | |||||
tempBuffer.append(((PSResource)params[i]).getResourceSpecification()); | |||||
} else { | |||||
throw new IllegalArgumentException("Unsupported parameter type: " | |||||
+ params[i].getClass().getName()); | |||||
} | |||||
} | |||||
} | |||||
writeln(tempBuffer.toString()); | |||||
} | |||||
/** | |||||
* Saves the graphics state of the rendering engine. | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void saveGraphicsState() throws IOException { | |||||
writeln("gsave"); | |||||
PSState state = new PSState(this.currentState, false); | |||||
this.graphicsStateStack.push(this.currentState); | |||||
this.currentState = state; | |||||
} | |||||
/** | |||||
* Restores the last graphics state of the rendering engine. | |||||
* @return true if the state was restored, false if there's a stack underflow. | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public boolean restoreGraphicsState() throws IOException { | |||||
if (this.graphicsStateStack.size() > 0) { | |||||
writeln("grestore"); | |||||
this.currentState = (PSState)this.graphicsStateStack.pop(); | |||||
return true; | |||||
} else { | |||||
return false; | |||||
} | |||||
} | |||||
/** | |||||
* Returns the current graphics state. | |||||
* @return the current graphics state | |||||
*/ | |||||
public PSState getCurrentState() { | |||||
return this.currentState; | |||||
} | |||||
/** | |||||
* Concats the transformation matrix. | |||||
* @param a A part | |||||
* @param b B part | |||||
* @param c C part | |||||
* @param d D part | |||||
* @param e E part | |||||
* @param f F part | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void concatMatrix(double a, double b, | |||||
double c, double d, | |||||
double e, double f) throws IOException { | |||||
AffineTransform at = new AffineTransform(a, b, c, d, e, f); | |||||
concatMatrix(at); | |||||
} | |||||
/** | |||||
* Concats the transformations matrix. | |||||
* @param matrix Matrix to use | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void concatMatrix(double[] matrix) throws IOException { | |||||
concatMatrix(matrix[0], matrix[1], | |||||
matrix[2], matrix[3], | |||||
matrix[4], matrix[5]); | |||||
} | |||||
/** | |||||
* Concats the transformations matric. | |||||
* @param at the AffineTransform whose matrix to use | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void concatMatrix(AffineTransform at) throws IOException { | |||||
double[] matrix = new double[6]; | |||||
at.getMatrix(matrix); | |||||
getCurrentState().concatMatrix(at); | |||||
writeln("[" + formatDouble5(matrix[0]) + " " | |||||
+ formatDouble5(matrix[1]) + " " | |||||
+ formatDouble5(matrix[2]) + " " | |||||
+ formatDouble5(matrix[3]) + " " | |||||
+ formatDouble5(matrix[4]) + " " | |||||
+ formatDouble5(matrix[5]) + "] concat"); | |||||
} | |||||
/** | |||||
* Adds a rectangle to the current path. | |||||
* @param x upper left corner | |||||
* @param y upper left corner | |||||
* @param w width | |||||
* @param h height | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void defineRect(double x, double y, double w, double h) | |||||
throws IOException { | |||||
writeln(formatDouble(x) | |||||
+ " " + formatDouble(y) | |||||
+ " " + formatDouble(w) | |||||
+ " " + formatDouble(h) | |||||
+ " re"); | |||||
} | |||||
/** | |||||
* Establishes the specified line cap style. | |||||
* @param linecap the line cap style (0, 1 or 2) as defined by the setlinecap command. | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void useLineCap(int linecap) throws IOException { | |||||
if (getCurrentState().useLineCap(linecap)) { | |||||
writeln(linecap + " setlinecap"); | |||||
} | |||||
} | |||||
/** | |||||
* Establishes the specified line width. | |||||
* @param width the line width as defined by the setlinewidth command. | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void useLineWidth(double width) throws IOException { | |||||
if (getCurrentState().useLineWidth(width)) { | |||||
writeln(formatDouble(width) + " setlinewidth"); | |||||
} | |||||
} | |||||
/** | |||||
* Establishes the specified dash pattern. | |||||
* @param pattern the dash pattern as defined by the setdash command. | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void useDash(String pattern) throws IOException { | |||||
if (pattern == null) { | |||||
pattern = PSState.DEFAULT_DASH; | |||||
} | |||||
if (getCurrentState().useDash(pattern)) { | |||||
writeln(pattern + " setdash"); | |||||
} | |||||
} | |||||
/** | |||||
* Establishes the specified color (RGB). | |||||
* @param col the color as defined by the setrgbcolor command. | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void useRGBColor(Color col) throws IOException { | |||||
if (col == null) { | |||||
col = PSState.DEFAULT_RGB_COLOR; | |||||
} | |||||
if (getCurrentState().useColor(col)) { | |||||
float[] comps = col.getColorComponents(null); | |||||
writeln(formatDouble(comps[0]) | |||||
+ " " + formatDouble(comps[1]) | |||||
+ " " + formatDouble(comps[2]) | |||||
+ " setrgbcolor"); | |||||
} | |||||
} | |||||
/** | |||||
* Establishes the specified font and size. | |||||
* @param name name of the font for the "F" command (see FOP Std Proc Set) | |||||
* @param size size of the font | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void useFont(String name, float size) throws IOException { | |||||
if (getCurrentState().useFont(name, size)) { | |||||
writeln(name + " " + formatDouble(size) + " F"); | |||||
} | |||||
} | |||||
private Set documentSuppliedResources; | |||||
private Set documentNeededResources; | |||||
private Set pageResources; | |||||
/** | |||||
* Notifies the generator that a new page has been started and that the page resource | |||||
* set can be cleared. | |||||
*/ | |||||
public void notifyStartNewPage() { | |||||
if (pageResources != null) { | |||||
pageResources.clear(); | |||||
} | |||||
} | |||||
/** | |||||
* Notifies the generator about the usage of a resource on the current page. | |||||
* @param res the resource being used | |||||
* @param needed true if this is a needed resource, false for a supplied resource | |||||
*/ | |||||
public void notifyResourceUsage(PSResource res, boolean needed) { | |||||
if (pageResources == null) { | |||||
pageResources = new java.util.HashSet(); | |||||
} | |||||
pageResources.add(res); | |||||
if (needed) { | |||||
if (documentNeededResources == null) { | |||||
documentNeededResources = new java.util.HashSet(); | |||||
} | |||||
documentNeededResources.add(res); | |||||
} else { | |||||
if (documentSuppliedResources == null) { | |||||
documentSuppliedResources = new java.util.HashSet(); | |||||
} | |||||
documentSuppliedResources.add(res); | |||||
} | |||||
} | |||||
/** | |||||
* Indicates whether a particular resource is supplied, rather than needed. | |||||
* @param res the resource | |||||
* @return true if the resource is registered as being supplied. | |||||
*/ | |||||
public boolean isResourceSupplied(PSResource res) { | |||||
return documentSuppliedResources.contains(res); | |||||
} | |||||
/** | |||||
* Writes a DSC comment for the accumulated used resources, either at page level or | |||||
* at document level. | |||||
* @param pageLevel true if the DSC comment for the page level should be generated, | |||||
* false for the document level (in the trailer) | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void writeResources(boolean pageLevel) throws IOException { | |||||
if (pageLevel) { | |||||
writeResourceComment(DSCConstants.PAGE_RESOURCES, pageResources); | |||||
} else { | |||||
writeResourceComment(DSCConstants.DOCUMENT_NEEDED_RESOURCES, | |||||
documentNeededResources); | |||||
writeResourceComment(DSCConstants.DOCUMENT_SUPPLIED_RESOURCES, | |||||
documentSuppliedResources); | |||||
} | |||||
} | |||||
private void writeResourceComment(String name, Set resources) throws IOException { | |||||
if (resources == null || resources.size() == 0) { | |||||
return; | |||||
} | |||||
tempBuffer.setLength(0); | |||||
tempBuffer.append("%%"); | |||||
tempBuffer.append(name); | |||||
tempBuffer.append(" "); | |||||
boolean first = true; | |||||
Iterator i = resources.iterator(); | |||||
while (i.hasNext()) { | |||||
if (!first) { | |||||
writeln(tempBuffer.toString()); | |||||
tempBuffer.setLength(0); | |||||
tempBuffer.append("%%+ "); | |||||
} | |||||
PSResource res = (PSResource)i.next(); | |||||
tempBuffer.append(res.getResourceSpecification()); | |||||
first = false; | |||||
} | |||||
writeln(tempBuffer.toString()); | |||||
} | |||||
/** Used for the ATEND constant. See there. */ | |||||
private static interface AtendIndicator { | |||||
} | |||||
} |
/* | /* | ||||
* Copyright 2005 The Apache Software Foundation. | |||||
* Copyright 2005-2006 The Apache Software Foundation. | |||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | ||||
import org.apache.fop.render.Graphics2DAdapter; | import org.apache.fop.render.Graphics2DAdapter; | ||||
import org.apache.fop.render.Graphics2DImagePainter; | import org.apache.fop.render.Graphics2DImagePainter; | ||||
import org.apache.fop.render.RendererContext; | import org.apache.fop.render.RendererContext; | ||||
import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; | |||||
import org.apache.xmlgraphics.ps.PSGenerator; | |||||
/** | /** | ||||
* Graphics2DAdapter implementation for PostScript. | * Graphics2DAdapter implementation for PostScript. | ||||
final boolean textAsShapes = false; | final boolean textAsShapes = false; | ||||
PSGraphics2D graphics = new PSGraphics2D(textAsShapes, gen); | PSGraphics2D graphics = new PSGraphics2D(textAsShapes, gen); | ||||
graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext()); | |||||
graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); | |||||
AffineTransform transform = new AffineTransform(); | AffineTransform transform = new AffineTransform(); | ||||
// scale to viewbox | // scale to viewbox | ||||
transform.translate(fx, fy); | transform.translate(fx, fy); |
package org.apache.fop.render.ps; | package org.apache.fop.render.ps; | ||||
import java.awt.Dimension; | import java.awt.Dimension; | ||||
import java.awt.color.ColorSpace; | |||||
import java.awt.geom.Rectangle2D; | import java.awt.geom.Rectangle2D; | ||||
import java.awt.image.ColorModel; | |||||
import java.awt.image.DataBuffer; | |||||
import java.awt.image.Raster; | |||||
import java.awt.image.RenderedImage; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.OutputStream; | |||||
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
import org.apache.commons.logging.LogFactory; | import org.apache.commons.logging.LogFactory; | ||||
import org.apache.fop.image.EPSImage; | import org.apache.fop.image.EPSImage; | ||||
import org.apache.fop.image.FopImage; | import org.apache.fop.image.FopImage; | ||||
import org.apache.fop.image.JpegImage; | import org.apache.fop.image.JpegImage; | ||||
import org.apache.fop.util.ASCII85OutputStream; | |||||
import org.apache.fop.util.Finalizable; | |||||
import org.apache.fop.util.FlateEncodeOutputStream; | |||||
import org.apache.fop.util.RunLengthEncodeOutputStream; | |||||
import org.apache.xmlgraphics.ps.PSGenerator; | |||||
/** | /** | ||||
* Utility code for rendering images in PostScript. | * Utility code for rendering images in PostScript. | ||||
*/ | */ | ||||
public class PSImageUtils { | |||||
public class PSImageUtils extends org.apache.xmlgraphics.ps.PSImageUtils { | |||||
/** logging instance */ | /** logging instance */ | ||||
protected static Log log = LogFactory.getLog(PSImageUtils.class); | protected static Log log = LogFactory.getLog(PSImageUtils.class); | ||||
img.getColorSpace(), gen); | img.getColorSpace(), gen); | ||||
} | } | ||||
private static void writeImage(byte[] img, | |||||
Dimension imgDim, String imgName, | |||||
Rectangle2D targetRect, | |||||
boolean isJPEG, ColorSpace colorSpace, | |||||
PSGenerator gen) throws IOException { | |||||
boolean iscolor = colorSpace.getType() != ColorSpace.CS_GRAY; | |||||
gen.saveGraphicsState(); | |||||
gen.writeln(gen.formatDouble(targetRect.getX()) + " " | |||||
+ gen.formatDouble(targetRect.getY()) + " translate"); | |||||
gen.writeln(gen.formatDouble(targetRect.getWidth()) + " " | |||||
+ gen.formatDouble(targetRect.getHeight()) + " scale"); | |||||
gen.commentln("%FOPBeginBitmap: " + imgName); | |||||
if (colorSpace.getType() == ColorSpace.TYPE_CMYK) { | |||||
gen.writeln("/DeviceCMYK setcolorspace"); | |||||
} else if (colorSpace.getType() == ColorSpace.CS_GRAY) { | |||||
gen.writeln("/DeviceGray setcolorspace"); | |||||
} else { | |||||
gen.writeln("/DeviceRGB setcolorspace"); | |||||
} | |||||
gen.writeln("{{"); | |||||
// Template: (RawData is used for the EOF signal only) | |||||
// gen.write("/RawData currentfile <first filter> filter def"); | |||||
// gen.write("/Data RawData <second filter> <third filter> [...] def"); | |||||
if (isJPEG) { | |||||
gen.writeln("/RawData currentfile /ASCII85Decode filter def"); | |||||
gen.writeln("/Data RawData << >> /DCTDecode filter def"); | |||||
} else { | |||||
if (gen.getPSLevel() >= 3) { | |||||
gen.writeln("/RawData currentfile /ASCII85Decode filter def"); | |||||
gen.writeln("/Data RawData /FlateDecode filter def"); | |||||
} else { | |||||
gen.writeln("/RawData currentfile /ASCII85Decode filter def"); | |||||
gen.writeln("/Data RawData /RunLengthDecode filter def"); | |||||
} | |||||
} | |||||
gen.writeln("<<"); | |||||
gen.writeln(" /ImageType 1"); | |||||
gen.writeln(" /Width " + imgDim.width); | |||||
gen.writeln(" /Height " + imgDim.height); | |||||
gen.writeln(" /BitsPerComponent 8"); | |||||
if (colorSpace.getType() == ColorSpace.TYPE_CMYK) { | |||||
if (false /*TODO img.invertImage()*/) { | |||||
gen.writeln(" /Decode [1 0 1 0 1 0 1 0]"); | |||||
} else { | |||||
gen.writeln(" /Decode [0 1 0 1 0 1 0 1]"); | |||||
} | |||||
} else if (iscolor) { | |||||
gen.writeln(" /Decode [0 1 0 1 0 1]"); | |||||
} else { | |||||
gen.writeln(" /Decode [0 1]"); | |||||
} | |||||
// Setup scanning for left-to-right and top-to-bottom | |||||
gen.writeln(" /ImageMatrix [" + imgDim.width + " 0 0 " | |||||
+ imgDim.height + " 0 0]"); | |||||
gen.writeln(" /DataSource Data"); | |||||
gen.writeln(">>"); | |||||
gen.writeln("image"); | |||||
/* the following two lines could be enabled if something still goes wrong | |||||
* gen.write("Data closefile"); | |||||
* gen.write("RawData flushfile"); | |||||
*/ | |||||
gen.writeln("} stopped {handleerror} if"); | |||||
gen.writeln(" RawData flushfile"); | |||||
gen.writeln("} exec"); | |||||
OutputStream out = gen.getOutputStream(); | |||||
out = new ASCII85OutputStream(out); | |||||
if (isJPEG) { | |||||
//nop | |||||
} else { | |||||
if (gen.getPSLevel() >= 3) { | |||||
out = new FlateEncodeOutputStream(out); | |||||
} else { | |||||
out = new RunLengthEncodeOutputStream(out); | |||||
} | |||||
} | |||||
out.write(img); | |||||
if (out instanceof Finalizable) { | |||||
((Finalizable)out).finalizeStream(); | |||||
} else { | |||||
out.flush(); | |||||
} | |||||
gen.writeln(""); | |||||
gen.commentln("%FOPEndBitmap"); | |||||
gen.restoreGraphicsState(); | |||||
} | |||||
/** | |||||
* Renders a bitmap image to PostScript. | |||||
* @param img image to render | |||||
* @param x x position | |||||
* @param y y position | |||||
* @param w width | |||||
* @param h height | |||||
* @param gen PS generator | |||||
* @throws IOException In case of an I/O problem while rendering the image | |||||
*/ | |||||
public static void renderBitmapImage(RenderedImage img, | |||||
float x, float y, float w, float h, PSGenerator gen) | |||||
throws IOException { | |||||
byte[] imgmap = getBitmapBytes(img); | |||||
String imgName = img.getClass().getName(); | |||||
Dimension imgDim = new Dimension(img.getWidth(), img.getHeight()); | |||||
Rectangle2D targetRect = new Rectangle2D.Double(x, y, w, h); | |||||
boolean isJPEG = false; | |||||
writeImage(imgmap, imgDim, imgName, targetRect, isJPEG, | |||||
img.getColorModel().getColorSpace(), gen); | |||||
} | |||||
private static byte[] getBitmapBytes(RenderedImage img) { | |||||
int[] tmpMap = getRGB(img, 0, 0, img.getWidth(), img.getHeight(), null, 0, img.getWidth()); | |||||
// Should take care of the ColorSpace and bitsPerPixel | |||||
byte[] bitmaps = new byte[img.getWidth() * img.getHeight() * 3]; | |||||
for (int y = 0, my = img.getHeight(); y < my; y++) { | |||||
for (int x = 0, mx = img.getWidth(); x < mx; x++) { | |||||
int p = tmpMap[y * mx + x]; | |||||
int r = (p >> 16) & 0xFF; | |||||
int g = (p >> 8) & 0xFF; | |||||
int b = (p) & 0xFF; | |||||
bitmaps[3 * (y * mx + x)] = (byte)(r & 0xFF); | |||||
bitmaps[3 * (y * mx + x) + 1] = (byte)(g & 0xFF); | |||||
bitmaps[3 * (y * mx + x) + 2] = (byte)(b & 0xFF); | |||||
} | |||||
} | |||||
return bitmaps; | |||||
} | |||||
public static int[] getRGB(RenderedImage img, | |||||
int startX, int startY, int w, int h, | |||||
int[] rgbArray, int offset, int scansize) { | |||||
Raster raster = img.getData(); | |||||
int yoff = offset; | |||||
int off; | |||||
Object data; | |||||
int nbands = raster.getNumBands(); | |||||
int dataType = raster.getDataBuffer().getDataType(); | |||||
switch (dataType) { | |||||
case DataBuffer.TYPE_BYTE: | |||||
data = new byte[nbands]; | |||||
break; | |||||
case DataBuffer.TYPE_USHORT: | |||||
data = new short[nbands]; | |||||
break; | |||||
case DataBuffer.TYPE_INT: | |||||
data = new int[nbands]; | |||||
break; | |||||
case DataBuffer.TYPE_FLOAT: | |||||
data = new float[nbands]; | |||||
break; | |||||
case DataBuffer.TYPE_DOUBLE: | |||||
data = new double[nbands]; | |||||
break; | |||||
default: | |||||
throw new IllegalArgumentException("Unknown data buffer type: "+ | |||||
dataType); | |||||
} | |||||
if (rgbArray == null) { | |||||
rgbArray = new int[offset+h*scansize]; | |||||
} | |||||
ColorModel colorModel = img.getColorModel(); | |||||
for (int y = startY; y < startY+h; y++, yoff+=scansize) { | |||||
off = yoff; | |||||
for (int x = startX; x < startX+w; x++) { | |||||
rgbArray[off++] = colorModel.getRGB(raster.getDataElements(x, | |||||
y, | |||||
data)); | |||||
} | |||||
} | |||||
return rgbArray; | |||||
} | |||||
public static void renderEPS(EPSImage img, | public static void renderEPS(EPSImage img, | ||||
float x, float y, float w, float h, | float x, float y, float w, float h, | ||||
PSGenerator gen) { | PSGenerator gen) { | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Places an EPS file in the PostScript stream. | |||||
* @param rawEPS byte array containing the raw EPS data | |||||
* @param name name for the EPS document | |||||
* @param x x-coordinate of viewport in millipoints | |||||
* @param y y-coordinate of viewport in millipoints | |||||
* @param w width of viewport in millipoints | |||||
* @param h height of viewport in millipoints | |||||
* @param bboxx x-coordinate of EPS bounding box in points | |||||
* @param bboxy y-coordinate of EPS bounding box in points | |||||
* @param bboxw width of EPS bounding box in points | |||||
* @param bboxh height of EPS bounding box in points | |||||
* @param gen the PS generator | |||||
* @throws IOException in case an I/O error happens during output | |||||
*/ | |||||
public static void renderEPS(byte[] rawEPS, String name, | |||||
float x, float y, float w, float h, | |||||
float bboxx, float bboxy, float bboxw, float bboxh, | |||||
PSGenerator gen) throws IOException { | |||||
gen.notifyResourceUsage(PSProcSets.EPS_PROCSET, false); | |||||
gen.writeln("%FOPBeginEPS: " + name); | |||||
gen.writeln("BeginEPSF"); | |||||
gen.writeln(gen.formatDouble(x) + " " + gen.formatDouble(y) + " translate"); | |||||
gen.writeln("0 " + gen.formatDouble(h) + " translate"); | |||||
gen.writeln("1 -1 scale"); | |||||
float sx = w / bboxw; | |||||
float sy = h / bboxh; | |||||
if (sx != 1 || sy != 1) { | |||||
gen.writeln(gen.formatDouble(sx) + " " + gen.formatDouble(sy) + " scale"); | |||||
} | |||||
if (bboxx != 0 || bboxy != 0) { | |||||
gen.writeln(gen.formatDouble(-bboxx) + " " + gen.formatDouble(-bboxy) + " translate"); | |||||
} | |||||
gen.writeln(gen.formatDouble(bboxy) + " " + gen.formatDouble(bboxy) | |||||
+ " " + gen.formatDouble(bboxw) + " " + gen.formatDouble(bboxh) + " re clip"); | |||||
gen.writeln("newpath"); | |||||
PSResource res = new PSResource(PSResource.TYPE_FILE, name); | |||||
gen.notifyResourceUsage(res, false); | |||||
gen.writeDSCComment(DSCConstants.BEGIN_DOCUMENT, res.getName()); | |||||
gen.writeByteArr(rawEPS); | |||||
gen.writeDSCComment(DSCConstants.END_DOCUMENT); | |||||
gen.writeln("EndEPSF"); | |||||
gen.writeln("%FOPEndEPS"); | |||||
} | |||||
} | } |
/* | |||||
* Copyright 2001-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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.render.ps; | |||||
import java.io.IOException; | |||||
/** | |||||
* This class defines the basic resources (procsets) used by FOP's PostScript | |||||
* renderer and SVG transcoder. | |||||
* | |||||
* @author <a href="mailto:fop-dev@xmlgraphics.apache.org">Apache FOP Development Team</a> | |||||
* @version $Id: PSProcSets.java,v 1.3 2003/03/11 08:42:24 jeremias Exp $ | |||||
*/ | |||||
public final class PSProcSets { | |||||
/** the standard FOP procset */ | |||||
public static final PSResource STD_PROCSET = new StdProcSet(); | |||||
/** the EPS FOP procset */ | |||||
public static final PSResource EPS_PROCSET = new EPSProcSet(); | |||||
private static class StdProcSet extends PSResource { | |||||
public StdProcSet() { | |||||
super("procset", "Apache FOP Std ProcSet"); | |||||
} | |||||
public void writeTo(PSGenerator gen) throws IOException { | |||||
gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, | |||||
new Object[] {"procset", getName(), "1.0", "0"}); | |||||
gen.writeDSCComment(DSCConstants.VERSION, | |||||
new Object[] {"1.0", "0"}); | |||||
gen.writeDSCComment(DSCConstants.COPYRIGHT, "Copyright 2001-2003 " | |||||
+ "The Apache Software Foundation. All rights reserved."); | |||||
gen.writeDSCComment(DSCConstants.TITLE, "Basic set of procedures used by FOP"); | |||||
gen.writeln("/bd{bind def}bind def"); | |||||
gen.writeln("/ld{load def}bd"); | |||||
gen.writeln("/M/moveto ld"); | |||||
gen.writeln("/RM/rmoveto ld"); | |||||
gen.writeln("/t/show ld"); | |||||
gen.writeln("/A/ashow ld"); | |||||
gen.writeln("/cp/closepath ld"); | |||||
gen.writeln("/re {4 2 roll M"); //define rectangle | |||||
gen.writeln("1 index 0 rlineto"); | |||||
gen.writeln("0 exch rlineto"); | |||||
gen.writeln("neg 0 rlineto"); | |||||
gen.writeln("cp } bd"); | |||||
gen.writeln("/_ctm matrix def"); //Holds the current matrix | |||||
gen.writeln("/_tm matrix def"); | |||||
//BT: save currentmatrix, set _tm to identitymatrix and move to 0/0 | |||||
gen.writeln("/BT { _ctm currentmatrix pop matrix _tm copy pop 0 0 moveto } bd"); | |||||
//ET: restore last currentmatrix | |||||
gen.writeln("/ET { _ctm setmatrix } bd"); | |||||
gen.writeln("/iTm { _ctm setmatrix _tm concat } bd"); | |||||
gen.writeln("/Tm { _tm astore pop iTm 0 0 moveto } bd"); | |||||
gen.writeln("/ux 0.0 def"); | |||||
gen.writeln("/uy 0.0 def"); | |||||
// <font> <size> F | |||||
gen.writeln("/F {"); | |||||
gen.writeln(" /Tp exch def"); | |||||
// gen.writeln(" currentdict exch get"); | |||||
gen.writeln(" /Tf exch def"); | |||||
gen.writeln(" Tf findfont Tp scalefont setfont"); | |||||
gen.writeln(" /cf Tf def /cs Tp def /cw ( ) stringwidth pop def"); | |||||
gen.writeln("} bd"); | |||||
gen.writeln("/ULS {currentpoint /uy exch def /ux exch def} bd"); | |||||
gen.writeln("/ULE {"); | |||||
gen.writeln(" /Tcx currentpoint pop def"); | |||||
gen.writeln(" gsave"); | |||||
gen.writeln(" newpath"); | |||||
gen.writeln(" cf findfont cs scalefont dup"); | |||||
gen.writeln(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup"); | |||||
gen.writeln(" /UnderlinePosition get Ts mul /To exch def"); | |||||
gen.writeln(" /UnderlineThickness get Ts mul /Tt exch def"); | |||||
gen.writeln(" ux uy To add moveto Tcx uy To add lineto"); | |||||
gen.writeln(" Tt setlinewidth stroke"); | |||||
gen.writeln(" grestore"); | |||||
gen.writeln("} bd"); | |||||
gen.writeln("/OLE {"); | |||||
gen.writeln(" /Tcx currentpoint pop def"); | |||||
gen.writeln(" gsave"); | |||||
gen.writeln(" newpath"); | |||||
gen.writeln(" cf findfont cs scalefont dup"); | |||||
gen.writeln(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup"); | |||||
gen.writeln(" /UnderlinePosition get Ts mul /To exch def"); | |||||
gen.writeln(" /UnderlineThickness get Ts mul /Tt exch def"); | |||||
gen.writeln(" ux uy To add cs add moveto Tcx uy To add cs add lineto"); | |||||
gen.writeln(" Tt setlinewidth stroke"); | |||||
gen.writeln(" grestore"); | |||||
gen.writeln("} bd"); | |||||
gen.writeln("/SOE {"); | |||||
gen.writeln(" /Tcx currentpoint pop def"); | |||||
gen.writeln(" gsave"); | |||||
gen.writeln(" newpath"); | |||||
gen.writeln(" cf findfont cs scalefont dup"); | |||||
gen.writeln(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup"); | |||||
gen.writeln(" /UnderlinePosition get Ts mul /To exch def"); | |||||
gen.writeln(" /UnderlineThickness get Ts mul /Tt exch def"); | |||||
gen.writeln(" ux uy To add cs 10 mul 26 idiv add moveto " | |||||
+ "Tcx uy To add cs 10 mul 26 idiv add lineto"); | |||||
gen.writeln(" Tt setlinewidth stroke"); | |||||
gen.writeln(" grestore"); | |||||
gen.writeln("} bd"); | |||||
gen.writeln("/QUADTO {"); | |||||
gen.writeln("/Y22 exch store"); | |||||
gen.writeln("/X22 exch store"); | |||||
gen.writeln("/Y21 exch store"); | |||||
gen.writeln("/X21 exch store"); | |||||
gen.writeln("currentpoint"); | |||||
gen.writeln("/Y21 load 2 mul add 3 div exch"); | |||||
gen.writeln("/X21 load 2 mul add 3 div exch"); | |||||
gen.writeln("/X21 load 2 mul /X22 load add 3 div"); | |||||
gen.writeln("/Y21 load 2 mul /Y22 load add 3 div"); | |||||
gen.writeln("/X22 load /Y22 load curveto"); | |||||
gen.writeln("} bd"); | |||||
gen.writeDSCComment(DSCConstants.END_RESOURCE); | |||||
} | |||||
} | |||||
private static class EPSProcSet extends PSResource { | |||||
public EPSProcSet() { | |||||
super("procset", "Apache FOP EPS ProcSet"); | |||||
} | |||||
public void writeTo(PSGenerator gen) throws IOException { | |||||
gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, | |||||
new Object[] {"procset", getName(), "1.0", "0"}); | |||||
gen.writeDSCComment(DSCConstants.VERSION, | |||||
new Object[] {"1.0", "0"}); | |||||
gen.writeDSCComment(DSCConstants.COPYRIGHT, "Copyright 2002-2003 " | |||||
+ "The Apache Software Foundation. All rights reserved."); | |||||
gen.writeDSCComment(DSCConstants.TITLE, "EPS procedures used by FOP"); | |||||
gen.writeln("/BeginEPSF { %def"); | |||||
gen.writeln("/b4_Inc_state save def % Save state for cleanup"); | |||||
gen.writeln("/dict_count countdictstack def % Count objects on dict stack"); | |||||
gen.writeln("/op_count count 1 sub def % Count objects on operand stack"); | |||||
gen.writeln("userdict begin % Push userdict on dict stack"); | |||||
gen.writeln("/showpage { } def % Redefine showpage, { } = null proc"); | |||||
gen.writeln("0 setgray 0 setlinecap % Prepare graphics state"); | |||||
gen.writeln("1 setlinewidth 0 setlinejoin"); | |||||
gen.writeln("10 setmiterlimit [ ] 0 setdash newpath"); | |||||
gen.writeln("/languagelevel where % If level not equal to 1 then"); | |||||
gen.writeln("{pop languagelevel % set strokeadjust and"); | |||||
gen.writeln("1 ne % overprint to their defaults."); | |||||
gen.writeln("{false setstrokeadjust false setoverprint"); | |||||
gen.writeln("} if"); | |||||
gen.writeln("} if"); | |||||
gen.writeln("} bd"); | |||||
gen.writeln("/EndEPSF { %def"); | |||||
gen.writeln("count op_count sub {pop} repeat % Clean up stacks"); | |||||
gen.writeln("countdictstack dict_count sub {end} repeat"); | |||||
gen.writeln("b4_Inc_state restore"); | |||||
gen.writeln("} bd"); | |||||
gen.writeDSCComment(DSCConstants.END_RESOURCE); | |||||
} | |||||
} | |||||
/** | |||||
* Generates a resource defining standard procset for FOP. | |||||
* @param gen PSGenerator to use for output | |||||
* @throws IOException In case of an I/O problem | |||||
*/ | |||||
public static void writeFOPStdProcSet(PSGenerator gen) throws IOException { | |||||
((StdProcSet)STD_PROCSET).writeTo(gen); | |||||
} | |||||
/** | |||||
* Generates a resource defining a procset for including EPS graphics. | |||||
* @param gen PSGenerator to use for output | |||||
* @throws IOException In case of an I/O problem | |||||
*/ | |||||
public static void writeFOPEPSProcSet(PSGenerator gen) throws IOException { | |||||
((EPSProcSet)EPS_PROCSET).writeTo(gen); | |||||
} | |||||
} |
import org.apache.fop.render.ps.extensions.PSSetupCode; | import org.apache.fop.render.ps.extensions.PSSetupCode; | ||||
import org.apache.fop.util.CharUtilities; | import org.apache.fop.util.CharUtilities; | ||||
import org.apache.xmlgraphics.ps.DSCConstants; | |||||
import org.apache.xmlgraphics.ps.PSGenerator; | |||||
import org.apache.xmlgraphics.ps.PSProcSets; | |||||
import org.apache.xmlgraphics.ps.PSResource; | |||||
import org.apache.xmlgraphics.ps.PSState; | |||||
import org.w3c.dom.Document; | import org.w3c.dom.Document; | ||||
/** | /** |
/* | |||||
* Copyright 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.render.ps; | |||||
/** | |||||
* Represents a PostScript resource (file, font, procset etc.). | |||||
*/ | |||||
public class PSResource { | |||||
/** a file resource */ | |||||
public static final String TYPE_FILE = "file"; | |||||
/** a font resource */ | |||||
public static final String TYPE_FONT = "font"; | |||||
/** a procset resource */ | |||||
public static final String TYPE_PROCSET = "procset"; | |||||
private String type; | |||||
private String name; | |||||
/** | |||||
* Main constructor | |||||
* @param type type of the resource | |||||
* @param name name of the resource | |||||
*/ | |||||
public PSResource(String type, String name) { | |||||
this.type = type; | |||||
this.name = name; | |||||
} | |||||
/** @return the type of the resource */ | |||||
public String getType() { | |||||
return this.type; | |||||
} | |||||
/** @return the name of the resource */ | |||||
public String getName() { | |||||
return this.name; | |||||
} | |||||
/** @return the <resource> specification as defined in DSC v3.0 spec. */ | |||||
public String getResourceSpecification() { | |||||
StringBuffer sb = new StringBuffer(); | |||||
sb.append(getType()).append(" ").append(PSGenerator.convertStringToDSC(getName())); | |||||
return sb.toString(); | |||||
} | |||||
} |
/* | /* | ||||
* Copyright 1999-2005 The Apache Software Foundation. | |||||
* Copyright 1999-2006 The Apache Software Foundation. | |||||
* | * | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | ||||
import org.apache.fop.render.XMLHandler; | import org.apache.fop.render.XMLHandler; | ||||
import org.apache.fop.render.RendererContext; | import org.apache.fop.render.RendererContext; | ||||
import org.apache.fop.svg.SVGUserAgent; | import org.apache.fop.svg.SVGUserAgent; | ||||
import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; | |||||
import org.apache.xmlgraphics.ps.PSGenerator; | |||||
// Commons-Logging | // Commons-Logging | ||||
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
context.getUserAgent().getSourcePixelUnitToMillimeter(), | context.getUserAgent().getSourcePixelUnitToMillimeter(), | ||||
new AffineTransform()); | new AffineTransform()); | ||||
PSGraphics2D graphics = new PSGraphics2D(strokeText, gen); | |||||
graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); | |||||
GVTBuilder builder = new GVTBuilder(); | GVTBuilder builder = new GVTBuilder(); | ||||
NativeTextHandler nativeTextHandler = null; | |||||
BridgeContext ctx = new BridgeContext(ua); | BridgeContext ctx = new BridgeContext(ua); | ||||
if (!strokeText) { | if (!strokeText) { | ||||
PSTextPainter textPainter = new PSTextPainter(psInfo.getFontInfo()); | |||||
nativeTextHandler = new NativeTextHandler(graphics, psInfo.getFontInfo()); | |||||
graphics.setCustomTextHandler(nativeTextHandler); | |||||
PSTextPainter textPainter = new PSTextPainter(nativeTextHandler); | |||||
ctx.setTextPainter(textPainter); | ctx.setTextPainter(textPainter); | ||||
PSTextElementBridge tBridge = new PSTextElementBridge(textPainter); | PSTextElementBridge tBridge = new PSTextElementBridge(textPainter); | ||||
ctx.putBridge(tBridge); | ctx.putBridge(tBridge); | ||||
gen.concatMatrix(vals); | gen.concatMatrix(vals); | ||||
}*/ | }*/ | ||||
final boolean textAsShapes = false; | |||||
PSGraphics2D graphics = new PSGraphics2D(textAsShapes, gen); | |||||
graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext()); | |||||
AffineTransform transform = new AffineTransform(); | AffineTransform transform = new AffineTransform(); | ||||
// scale to viewbox | // scale to viewbox | ||||
transform.translate(xOffset, yOffset); | transform.translate(xOffset, yOffset); |
/* | |||||
* 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.render.ps; | |||||
import java.io.IOException; | |||||
import java.io.Serializable; | |||||
import java.util.List; | |||||
import java.awt.Color; | |||||
import java.awt.geom.AffineTransform; | |||||
/** | |||||
* This class holds the current state of the PostScript interpreter. | |||||
* | |||||
* @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a> | |||||
* @version $Id$ | |||||
*/ | |||||
public class PSState implements Serializable { | |||||
/** Default for setdash */ | |||||
public static final String DEFAULT_DASH = "[] 0"; | |||||
/** Default color in PostScript */ | |||||
public static final Color DEFAULT_RGB_COLOR = Color.black; | |||||
private AffineTransform transform = new AffineTransform(); | |||||
private List transformConcatList = new java.util.ArrayList(); | |||||
private int linecap = 0; | |||||
private double linewidth = 1.0f; | |||||
private String dashpattern = DEFAULT_DASH; | |||||
private Color rgbColor = DEFAULT_RGB_COLOR; | |||||
//Font state | |||||
private String fontname; | |||||
private float fontsize; | |||||
/** | |||||
* Default constructor | |||||
*/ | |||||
public PSState() { | |||||
//nop | |||||
} | |||||
/** | |||||
* Copy constructor | |||||
* @param org the original to copy from | |||||
* @param copyTransforms true if the list of matrix concats should be cloned, too | |||||
*/ | |||||
public PSState(PSState org, boolean copyTransforms) { | |||||
this.transform = (AffineTransform)org.transform.clone(); | |||||
if (copyTransforms) { | |||||
this.transformConcatList.addAll(org.transformConcatList); | |||||
} | |||||
this.linecap = org.linecap; | |||||
this.linewidth = org.linewidth; | |||||
this.dashpattern = org.dashpattern; | |||||
this.rgbColor = org.rgbColor; | |||||
this.fontname = org.fontname; | |||||
this.fontsize = org.fontsize; | |||||
} | |||||
/** | |||||
* Returns the transform. | |||||
* @return the current transformation matrix | |||||
*/ | |||||
public AffineTransform getTransform() { | |||||
return this.transform; | |||||
} | |||||
/** | |||||
* Check the current transform. | |||||
* The transform for the current state is the combination of all | |||||
* transforms in the current state. The parameter is compared | |||||
* against this current transform. | |||||
* | |||||
* @param tf the transform the check against | |||||
* @return true if the new transform is different then the current transform | |||||
*/ | |||||
public boolean checkTransform(AffineTransform tf) { | |||||
return !tf.equals(this.transform); | |||||
} | |||||
/** | |||||
* Concats the given transformation matrix with the current one. | |||||
* @param transform The new transformation matrix | |||||
*/ | |||||
public void concatMatrix(AffineTransform transform) { | |||||
this.transformConcatList.add(transform); | |||||
this.transform.concatenate(transform); | |||||
} | |||||
/** | |||||
* Establishes the specified line cap. | |||||
* @param value line cap (0, 1 or 2) as defined by the setlinecap command | |||||
* @return true if the line cap changed compared to the previous setting | |||||
*/ | |||||
public boolean useLineCap(int value) { | |||||
if (linecap != value) { | |||||
linecap = value; | |||||
return true; | |||||
} else { | |||||
return false; | |||||
} | |||||
} | |||||
/** | |||||
* Establishes the specified line width. | |||||
* @param value line width as defined by the setlinewidth command | |||||
* @return true if the line width changed compared to the previous setting | |||||
*/ | |||||
public boolean useLineWidth(double value) { | |||||
if (linewidth != value) { | |||||
linewidth = value; | |||||
return true; | |||||
} else { | |||||
return false; | |||||
} | |||||
} | |||||
/** | |||||
* Establishes the specified dash. | |||||
* @param pattern dash pattern as defined by the setdash command | |||||
* @return true if the dash pattern changed compared to the previous setting | |||||
*/ | |||||
public boolean useDash(String pattern) { | |||||
if (!dashpattern.equals(pattern)) { | |||||
dashpattern = pattern; | |||||
return true; | |||||
} else { | |||||
return false; | |||||
} | |||||
} | |||||
/** | |||||
* Establishes the specified color (RGB). | |||||
* @param value color as defined by the setrgbcolor command | |||||
* @return true if the color changed compared to the previous setting | |||||
*/ | |||||
public boolean useColor(Color value) { | |||||
if (!rgbColor.equals(value)) { | |||||
rgbColor = value; | |||||
return true; | |||||
} else { | |||||
return false; | |||||
} | |||||
} | |||||
/** | |||||
* Establishes the specified font and size. | |||||
* @param name name of the font for the "F" command (see FOP Std Proc Set) | |||||
* @param size size of the font | |||||
* @return true if the font changed compared to the previous setting | |||||
*/ | |||||
public boolean useFont(String name, float size) { | |||||
if (name == null) { | |||||
throw new NullPointerException("font name must not be null"); | |||||
} | |||||
if (fontname == null || !fontname.equals(name) || fontsize != size) { | |||||
fontname = name; | |||||
fontsize = size; | |||||
return true; | |||||
} else { | |||||
return false; | |||||
} | |||||
} | |||||
/** | |||||
* Reestablishes the graphics state represented by this instance by issueing the | |||||
* necessary commands. | |||||
* @param gen The generator to use for output | |||||
* @exception IOException In case of an I/O problem | |||||
*/ | |||||
public void reestablish(PSGenerator gen) throws IOException { | |||||
for (int i = 0, len = transformConcatList.size(); i < len; i++) { | |||||
gen.concatMatrix((AffineTransform)transformConcatList.get(i)); | |||||
} | |||||
gen.useLineCap(linecap); | |||||
gen.useLineWidth(linewidth); | |||||
gen.useDash(dashpattern); | |||||
gen.useRGBColor(rgbColor); | |||||
if (fontname != null) { | |||||
gen.useFont(fontname, fontsize); | |||||
} | |||||
} | |||||
} |
import java.awt.Paint; | import java.awt.Paint; | ||||
import java.awt.Stroke; | import java.awt.Stroke; | ||||
import java.awt.Color; | import java.awt.Color; | ||||
import java.io.IOException; | |||||
import java.util.List; | import java.util.List; | ||||
import java.util.Iterator; | import java.util.Iterator; | ||||
import org.apache.commons.logging.Log; | |||||
import org.apache.commons.logging.LogFactory; | |||||
import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; | |||||
import org.apache.batik.dom.svg.SVGOMTextElement; | import org.apache.batik.dom.svg.SVGOMTextElement; | ||||
import org.apache.batik.gvt.text.Mark; | import org.apache.batik.gvt.text.Mark; | ||||
import org.apache.batik.gvt.TextPainter; | import org.apache.batik.gvt.TextPainter; | ||||
import org.apache.batik.gvt.text.TextPaintInfo; | import org.apache.batik.gvt.text.TextPaintInfo; | ||||
import org.apache.batik.gvt.font.GVTFontFamily; | import org.apache.batik.gvt.font.GVTFontFamily; | ||||
import org.apache.batik.gvt.renderer.StrokingTextPainter; | import org.apache.batik.gvt.renderer.StrokingTextPainter; | ||||
import org.apache.commons.logging.Log; | |||||
import org.apache.commons.logging.LogFactory; | |||||
import org.apache.fop.fonts.Font; | import org.apache.fop.fonts.Font; | ||||
import org.apache.fop.fonts.FontInfo; | import org.apache.fop.fonts.FontInfo; | ||||
/** the logger for this class */ | /** the logger for this class */ | ||||
protected Log log = LogFactory.getLog(PSTextPainter.class); | protected Log log = LogFactory.getLog(PSTextPainter.class); | ||||
private FontInfo fontInfo; | |||||
private NativeTextHandler nativeTextHandler; | |||||
//private FontInfo fontInfo; | |||||
/** | /** | ||||
* Use the stroking text painter to get the bounds and shape. | * Use the stroking text painter to get the bounds and shape. | ||||
/** | /** | ||||
* Create a new PS text painter with the given font information. | * Create a new PS text painter with the given font information. | ||||
* @param fontInfo the FontInfo object | |||||
* @param nativeTextHandler the NativeTextHandler instance used for text painting | |||||
*/ | */ | ||||
public PSTextPainter(FontInfo fontInfo) { | |||||
this.fontInfo = fontInfo; | |||||
public PSTextPainter(NativeTextHandler nativeTextHandler) { | |||||
this.nativeTextHandler = nativeTextHandler; | |||||
} | } | ||||
/** | /** | ||||
Object rcDel = aci.getAttribute( | Object rcDel = aci.getAttribute( | ||||
GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER); | GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER); | ||||
if (!(rcDel instanceof SVGOMTextElement)) { | |||||
//Batik 1.6 returns null here which makes it impossible to determine whether this can | |||||
//be painted or not, i.e. fall back to stroking. :-( | |||||
if (/*rcDel != null &&*/ !(rcDel instanceof SVGOMTextElement)) { | |||||
log.trace("-> spans found"); | log.trace("-> spans found"); | ||||
hasunsupported = true; //Filter spans | hasunsupported = true; //Filter spans | ||||
} | } | ||||
} | } | ||||
//Finally draw text | //Finally draw text | ||||
if (g2d instanceof PSGraphics2D) { | |||||
((PSGraphics2D) g2d).setOverrideFont(font); | |||||
} | |||||
nativeTextHandler.setOverrideFont(font); | |||||
try { | try { | ||||
g2d.drawString(txt, (float)(loc.getX() + tx), (float)(loc.getY())); | |||||
} finally { | |||||
if (g2d instanceof PSGraphics2D) { | |||||
((PSGraphics2D) g2d).setOverrideFont(null); | |||||
try { | |||||
nativeTextHandler.drawString(txt, (float)(loc.getX() + tx), (float)(loc.getY())); | |||||
} catch (IOException ioe) { | |||||
if (g2d instanceof PSGraphics2D) { | |||||
((PSGraphics2D)g2d).handleIOException(ioe); | |||||
} | |||||
} | } | ||||
} finally { | |||||
nativeTextHandler.setOverrideFont(null); | |||||
} | } | ||||
loc.setLocation(loc.getX() + (double)advance, loc.getY()); | loc.setLocation(loc.getX() + (double)advance, loc.getY()); | ||||
return loc; | return loc; | ||||
int weight = getWeight(aci); | int weight = getWeight(aci); | ||||
boolean found = false; | boolean found = false; | ||||
FontInfo fontInfo = nativeTextHandler.getFontInfo(); | |||||
String fontFamily = null; | String fontFamily = null; | ||||
List gvtFonts = (List) aci.getAttribute( | List gvtFonts = (List) aci.getAttribute( | ||||
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES); | GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES); |
package org.apache.fop.render.ps; | package org.apache.fop.render.ps; | ||||
import org.apache.xmlgraphics.java2d.ps.AbstractPSDocumentGraphics2D; | |||||
import org.apache.xmlgraphics.java2d.ps.PSDocumentGraphics2D; | |||||
/** | /** | ||||
* This class enables to transcode an input to a PostScript document. | * This class enables to transcode an input to a PostScript document. | ||||
* millimeter conversion factor. | * millimeter conversion factor. | ||||
* | * | ||||
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> | ||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | |||||
* @version $Id$ | * @version $Id$ | ||||
*/ | */ | ||||
public class PSTranscoder extends AbstractPSTranscoder { | public class PSTranscoder extends AbstractPSTranscoder { | ||||
super(); | super(); | ||||
} | } | ||||
/** @see AbstractPSTranscoder#createDocumentGraphics2D() */ | |||||
protected AbstractPSDocumentGraphics2D createDocumentGraphics2D() { | protected AbstractPSDocumentGraphics2D createDocumentGraphics2D() { | ||||
return new PSDocumentGraphics2D(false); | return new PSDocumentGraphics2D(false); | ||||
} | } |
/* | |||||
* Copyright 1999-2004 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.util; | |||||
/** | |||||
* This interface defines constants used by the ASCII85 filters. | |||||
* | |||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | |||||
* @version $Id$ | |||||
*/ | |||||
public interface ASCII85Constants { | |||||
/** Special character "z" stands for four NULL bytes (short-cut for !!!!!) */ | |||||
public static final int ZERO = 0x7A; //"z" | |||||
/** ZERO as a byte array */ | |||||
public static final byte[] ZERO_ARRAY = {(byte)ZERO}; | |||||
/** The start index for ASCII85 characters (!) */ | |||||
public static final int START = 0x21; //"!" | |||||
/** The end index for ASCII85 characters (u) */ | |||||
public static final int END = 0x75; //"u" | |||||
/** The EOL indicator (LF) */ | |||||
public static final int EOL = 0x0A; //"\n" | |||||
/** The EOD (end of data) indicator */ | |||||
public static final byte[] EOD = {0x7E, 0x3E}; //"~>" | |||||
/** Array of powers of 85 (4, 3, 2, 1, 0) */ | |||||
public static final long POW85[] = new long[] {85 * 85 * 85 * 85, | |||||
85 * 85 * 85, | |||||
85 * 85, | |||||
85, | |||||
1}; | |||||
/* | |||||
public static final long BASE85_4 = 85; | |||||
public static final long BASE85_3 = BASE85_4 * BASE85_4; | |||||
public static final long BASE85_2 = BASE85_3 * BASE85_4; | |||||
public static final long BASE85_1 = BASE85_2 * BASE85_4; | |||||
*/ | |||||
} | |||||
/* | |||||
* Copyright 1999-2004 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.util; | |||||
import java.io.InputStream; | |||||
import java.io.IOException; | |||||
/** | |||||
* This class applies a ASCII85 decoding to the stream. | |||||
* <p> | |||||
* The class is derived from InputStream instead of FilteredInputStream because | |||||
* we can use the read(byte[], int, int) method from InputStream which simply | |||||
* delegates to read(). This makes the implementation easier. | |||||
* <p> | |||||
* The filter is described in chapter 3.13.3 of the PostScript Language | |||||
* Reference (third edition). | |||||
* | |||||
* @version $Id$ | |||||
*/ | |||||
public class ASCII85InputStream extends InputStream | |||||
implements ASCII85Constants { | |||||
private InputStream in; | |||||
private boolean eodReached = false; | |||||
private int[] b = new int[4]; //decoded | |||||
private int bSize = 0; | |||||
private int bIndex = 0; | |||||
/** @see java.io.FilterInputStream **/ | |||||
public ASCII85InputStream(InputStream in) { | |||||
super(); | |||||
this.in = in; | |||||
} | |||||
/** @see java.io.FilterInputStream **/ | |||||
public int read() throws IOException { | |||||
//Check if we need to read the next tuple | |||||
if (bIndex >= bSize) { | |||||
if (eodReached) { | |||||
return -1; | |||||
} | |||||
readNextTuple(); | |||||
if (bSize == 0) { | |||||
if (!eodReached) { | |||||
throw new IllegalStateException("Internal error"); | |||||
} | |||||
return -1; | |||||
} | |||||
} | |||||
int result = b[bIndex]; | |||||
result = (result < 0 ? 256 + result : result); | |||||
bIndex++; | |||||
return result; | |||||
} | |||||
private int filteredRead() throws IOException { | |||||
int buf; | |||||
while (true) { | |||||
buf = in.read(); | |||||
switch (buf) { | |||||
case 0: //null | |||||
case 9: //tab | |||||
case 10: //LF | |||||
case 12: //FF | |||||
case 13: //CR | |||||
case 32: //space | |||||
continue; //ignore | |||||
case ZERO: | |||||
case 126: //= EOD[0] = '~' | |||||
return buf; | |||||
default: | |||||
if ((buf >= START) && (buf <= END)) { | |||||
return buf; | |||||
} else { | |||||
throw new IOException("Illegal character detected: " + buf); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
private void handleEOD() throws IOException { | |||||
final int buf = in.read(); | |||||
if (buf != EOD[1]) { | |||||
throw new IOException("'>' expected after '~' (EOD)"); | |||||
} | |||||
eodReached = true; | |||||
bSize = 0; | |||||
bIndex = 0; | |||||
} | |||||
private void readNextTuple() throws IOException { | |||||
int buf; | |||||
long tuple = 0; | |||||
//Read ahead and check for special "z" | |||||
buf = filteredRead(); | |||||
if (buf == ZERO) { | |||||
java.util.Arrays.fill(b, 0); | |||||
bSize = 4; | |||||
bIndex = 0; | |||||
} else if (buf == EOD[0]) { | |||||
handleEOD(); | |||||
} else { | |||||
int cIndex = 0; | |||||
tuple = (buf - START) * POW85[cIndex]; | |||||
cIndex++; | |||||
while (cIndex < 5) { | |||||
buf = filteredRead(); | |||||
if (buf == EOD[0]) { | |||||
handleEOD(); | |||||
break; | |||||
} else if (buf == ZERO) { | |||||
//Violation 2 | |||||
throw new IOException("Illegal 'z' within tuple"); | |||||
} else { | |||||
tuple += (buf - START) * POW85[cIndex]; | |||||
cIndex++; | |||||
} | |||||
} | |||||
int cSize = cIndex; | |||||
if (cSize == 1) { | |||||
//Violation 3 | |||||
throw new IOException("Only one character in tuple"); | |||||
} | |||||
//Handle optional, trailing, incomplete tuple | |||||
while (cIndex < 5) { | |||||
tuple += POW85[cIndex - 1]; | |||||
cIndex++; | |||||
} | |||||
if (tuple > (2L << 31) - 1) { | |||||
//Violation 1 | |||||
throw new IOException("Illegal tuple (> 2^32 - 1)"); | |||||
} | |||||
//Convert tuple | |||||
b[0] = (byte)((tuple >> 24) & 0xFF); | |||||
b[1] = (byte)((tuple >> 16) & 0xFF); | |||||
b[2] = (byte)((tuple >> 8) & 0xFF); | |||||
b[3] = (byte)((tuple) & 0xFF); | |||||
bSize = cSize - 1; | |||||
bIndex = 0; | |||||
} | |||||
} | |||||
} | |||||
/* | |||||
* Copyright 1999-2004 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.util; | |||||
import java.io.OutputStream; | |||||
import java.io.FilterOutputStream; | |||||
import java.io.IOException; | |||||
/** | |||||
* This class applies a ASCII85 encoding to the stream. | |||||
* | |||||
* @version $Id$ | |||||
*/ | |||||
public class ASCII85OutputStream extends FilterOutputStream | |||||
implements ASCII85Constants, Finalizable { | |||||
private static final boolean DEBUG = false; | |||||
private int pos = 0; | |||||
private long buffer = 0; | |||||
private int posinline = 0; | |||||
private int bw = 0; | |||||
/** @see java.io.FilterOutputStream **/ | |||||
public ASCII85OutputStream(OutputStream out) { | |||||
super(out); | |||||
} | |||||
/** @see java.io.FilterOutputStream **/ | |||||
public void write(int b) throws IOException { | |||||
if (pos == 0) { | |||||
buffer += (b << 24) & 0xff000000L; | |||||
} else if (pos == 1) { | |||||
buffer += (b << 16) & 0xff0000L; | |||||
} else if (pos == 2) { | |||||
buffer += (b << 8) & 0xff00L; | |||||
} else { | |||||
buffer += b & 0xffL; | |||||
} | |||||
pos++; | |||||
if (pos > 3) { | |||||
checkedWrite(convertWord(buffer)); | |||||
buffer = 0; | |||||
pos = 0; | |||||
} | |||||
} | |||||
/* UNUSED ATM | |||||
private void checkedWrite(int b) throws IOException { | |||||
if (posinline == 80) { | |||||
out.write(EOL); bw++; | |||||
posinline = 0; | |||||
} | |||||
checkedWrite(b); | |||||
posinline++; | |||||
bw++; | |||||
}*/ | |||||
private void checkedWrite(byte[] buf) throws IOException { | |||||
checkedWrite(buf, buf.length, false); | |||||
} | |||||
private void checkedWrite(byte[] buf, boolean nosplit) throws IOException { | |||||
checkedWrite(buf, buf.length, nosplit); | |||||
} | |||||
private void checkedWrite(byte[] buf , int len) throws IOException { | |||||
checkedWrite(buf, len, false); | |||||
} | |||||
private void checkedWrite(byte[] buf , int len, boolean nosplit) throws IOException { | |||||
if (posinline + len > 80) { | |||||
int firstpart = (nosplit ? 0 : len - (posinline + len - 80)); | |||||
if (firstpart > 0) { | |||||
out.write(buf, 0, firstpart); | |||||
} | |||||
out.write(EOL); bw++; | |||||
int rest = len - firstpart; | |||||
if (rest > 0) { | |||||
out.write(buf, firstpart, rest); | |||||
} | |||||
posinline = rest; | |||||
} else { | |||||
out.write(buf, 0, len); | |||||
posinline += len; | |||||
} | |||||
bw += len; | |||||
} | |||||
/** | |||||
* This converts a 32 bit value (4 bytes) into 5 bytes using base 85. | |||||
* each byte in the result starts with zero at the '!' character so | |||||
* the resulting base85 number fits into printable ascii chars | |||||
* | |||||
* @param word the 32 bit unsigned (hence the long datatype) word | |||||
* @return 5 bytes (or a single byte of the 'z' character for word | |||||
* values of 0) | |||||
*/ | |||||
private byte[] convertWord(long word) { | |||||
word = word & 0xffffffff; | |||||
if (word == 0) { | |||||
return ZERO_ARRAY; | |||||
} else { | |||||
if (word < 0) { | |||||
word = -word; | |||||
} | |||||
byte c1 = | |||||
(byte)((word | |||||
/ POW85[0]) & 0xFF); | |||||
byte c2 = | |||||
(byte)(((word - (c1 * POW85[0])) | |||||
/ POW85[1]) & 0xFF); | |||||
byte c3 = | |||||
(byte)(((word - (c1 * POW85[0]) | |||||
- (c2 * POW85[1])) | |||||
/ POW85[2]) & 0xFF); | |||||
byte c4 = | |||||
(byte)(((word - (c1 * POW85[0]) | |||||
- (c2 * POW85[1]) | |||||
- (c3 * POW85[2])) | |||||
/ POW85[3]) & 0xFF); | |||||
byte c5 = | |||||
(byte)(((word - (c1 * POW85[0]) | |||||
- (c2 * POW85[1]) | |||||
- (c3 * POW85[2]) | |||||
- (c4 * POW85[3]))) | |||||
& 0xFF); | |||||
byte[] ret = { | |||||
(byte)(c1 + START), (byte)(c2 + START), | |||||
(byte)(c3 + START), (byte)(c4 + START), | |||||
(byte)(c5 + START) | |||||
}; | |||||
if (DEBUG) { | |||||
for (int i = 0; i < ret.length; i++) { | |||||
if (ret[i] < 33 || ret[i] > 117) { | |||||
System.out.println("Illegal char value " | |||||
+ new Integer(ret[i])); | |||||
} | |||||
} | |||||
} | |||||
return ret; | |||||
} | |||||
} | |||||
/** @see Finalizable **/ | |||||
public void finalizeStream() throws IOException { | |||||
// now take care of the trailing few bytes. | |||||
// with n leftover bytes, we append 0 bytes to make a full group of 4 | |||||
// then convert like normal (except not applying the special zero rule) | |||||
// and write out the first n+1 bytes from the result | |||||
if (pos > 0) { | |||||
int rest = pos; | |||||
/* | |||||
byte[] lastdata = new byte[4]; | |||||
int i = 0; | |||||
for (int j = 0; j < 4; j++) { | |||||
if (j < rest) { | |||||
lastdata[j] = data[i++]; | |||||
} else { | |||||
lastdata[j] = 0; | |||||
} | |||||
} | |||||
long val = ((lastdata[0] << 24) & 0xff000000L) | |||||
+ ((lastdata[1] << 16) & 0xff0000L) | |||||
+ ((lastdata[2] << 8) & 0xff00L) | |||||
+ (lastdata[3] & 0xffL); | |||||
*/ | |||||
byte[] conv; | |||||
// special rule for handling zeros at the end | |||||
if (buffer != 0) { | |||||
conv = convertWord(buffer); | |||||
} else { | |||||
conv = new byte[5]; | |||||
for (int j = 0; j < 5; j++) { | |||||
conv[j] = (byte)'!'; | |||||
} | |||||
} | |||||
// assert rest+1 <= 5 | |||||
checkedWrite(conv, rest + 1); | |||||
} | |||||
// finally write the two character end of data marker | |||||
checkedWrite(EOD, true); | |||||
flush(); | |||||
if (out instanceof Finalizable) { | |||||
((Finalizable)out).finalizeStream(); | |||||
} | |||||
} | |||||
/** @see java.io.FilterOutputStream **/ | |||||
public void close() throws IOException { | |||||
finalizeStream(); | |||||
super.close(); | |||||
} | |||||
} | |||||
/* | |||||
* Copyright 1999-2004 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.util; | |||||
import java.io.OutputStream; | |||||
import java.io.FilterOutputStream; | |||||
import java.io.IOException; | |||||
/** | |||||
* This class applies a ASCII Hex encoding to the stream. | |||||
* | |||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | |||||
* @version $Id$ | |||||
*/ | |||||
public class ASCIIHexOutputStream extends FilterOutputStream | |||||
implements Finalizable { | |||||
private static final int EOL = 0x0A; //"\n" | |||||
private static final int EOD = 0x3E; //">" | |||||
private static final int ZERO = 0x30; //"0" | |||||
private static final int NINE = 0x39; //"9" | |||||
private static final int A = 0x41; //"A" | |||||
private static final int ADIFF = A - NINE - 1; | |||||
private int posinline = 0; | |||||
/** @see java.io.FilterOutputStream **/ | |||||
public ASCIIHexOutputStream(OutputStream out) { | |||||
super(out); | |||||
} | |||||
/** @see java.io.FilterOutputStream **/ | |||||
public void write(int b) throws IOException { | |||||
b &= 0xFF; | |||||
int digit1 = ((b & 0xF0) >> 4) + ZERO; | |||||
if (digit1 > NINE) { | |||||
digit1 += ADIFF; | |||||
} | |||||
out.write(digit1); | |||||
int digit2 = (b & 0x0F) + ZERO; | |||||
if (digit2 > NINE) { | |||||
digit2 += ADIFF; | |||||
} | |||||
out.write(digit2); | |||||
posinline++; | |||||
checkLineWrap(); | |||||
} | |||||
private void checkLineWrap() throws IOException { | |||||
//Maximum line length is 80 characters | |||||
if (posinline >= 40) { | |||||
out.write(EOL); | |||||
posinline = 0; | |||||
} | |||||
} | |||||
/** @see Finalizable **/ | |||||
public void finalizeStream() throws IOException { | |||||
checkLineWrap(); | |||||
//Write closing character ">" | |||||
super.write(EOD); | |||||
flush(); | |||||
if (out instanceof Finalizable) { | |||||
((Finalizable) out).finalizeStream(); | |||||
} | |||||
} | |||||
/** @see java.io.FilterOutputStream **/ | |||||
public void close() throws IOException { | |||||
finalizeStream(); | |||||
super.close(); | |||||
} | |||||
} | |||||
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
import org.apache.commons.logging.LogFactory; | import org.apache.commons.logging.LogFactory; | ||||
import org.apache.fop.util.Service; | |||||
import org.apache.xmlgraphics.util.Service; | |||||
/** | /** | ||||
* This class holds references to various XML handlers used by FOP. It also | * This class holds references to various XML handlers used by FOP. It also | ||||
Iterator providers = Service.providers(ContentHandlerFactory.class); | Iterator providers = Service.providers(ContentHandlerFactory.class); | ||||
if (providers != null) { | if (providers != null) { | ||||
while (providers.hasNext()) { | while (providers.hasNext()) { | ||||
String str = (String)providers.next(); | |||||
ContentHandlerFactory factory = (ContentHandlerFactory)providers.next(); | |||||
try { | try { | ||||
if (log.isDebugEnabled()) { | if (log.isDebugEnabled()) { | ||||
log.debug("Dynamically adding ContentHandlerFactory: " + str); | |||||
log.debug("Dynamically adding ContentHandlerFactory: " | |||||
+ factory.getClass().getName()); | |||||
} | } | ||||
addContentHandlerFactory(str); | |||||
addContentHandlerFactory(factory); | |||||
} catch (IllegalArgumentException e) { | } catch (IllegalArgumentException e) { | ||||
log.error("Error while adding ContentHandlerFactory", e); | log.error("Error while adding ContentHandlerFactory", e); | ||||
} | } |
/* | |||||
* Copyright 1999-2004 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.util; | |||||
/** | |||||
* This interface is used for special FilteredOutputStream classes that won't | |||||
* be closed (since this causes the target OutputStream to be closed, too) but | |||||
* where flush() is not enough, for example because a final marker has to be | |||||
* written to the target stream. | |||||
* | |||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | |||||
* @version $Id$ | |||||
*/ | |||||
public interface Finalizable { | |||||
/** | |||||
* This method can be called instead of close() on a subclass of | |||||
* FilteredOutputStream when a final marker has to be written to the target | |||||
* stream, but close() cannot be called. | |||||
* | |||||
* @exception java.io.IOException In case of an IO problem | |||||
*/ | |||||
void finalizeStream() | |||||
throws java.io.IOException; | |||||
} |
/* | |||||
* Copyright 1999-2004 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.util; | |||||
import java.io.OutputStream; | |||||
import java.io.IOException; | |||||
/** | |||||
* This class applies a FlateEncode filter to the stream. It is basically the | |||||
* normal DeflaterOutputStream except now also implementing the Finalizable | |||||
* interface. | |||||
* | |||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | |||||
* @version $Id$ | |||||
*/ | |||||
public class FlateEncodeOutputStream extends java.util.zip.DeflaterOutputStream | |||||
implements Finalizable { | |||||
/** @see java.util.zip.DeflaterOutputStream **/ | |||||
public FlateEncodeOutputStream(OutputStream out) { | |||||
super(out); | |||||
} | |||||
/** @see Finalizable **/ | |||||
public void finalizeStream() throws IOException { | |||||
finish(); | |||||
flush(); | |||||
if (out instanceof Finalizable) { | |||||
((Finalizable)out).finalizeStream(); | |||||
} | |||||
} | |||||
} | |||||
/* | |||||
* Copyright 1999-2004 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.util; | |||||
import java.io.FilterOutputStream; | |||||
import java.io.OutputStream; | |||||
import java.io.IOException; | |||||
/** | |||||
* This class applies a RunLengthEncode filter to the stream. | |||||
* | |||||
* @author <a href="mailto:smwolke@geistig.com">Stephen Wolke</a> | |||||
* @version $Id$ | |||||
*/ | |||||
public class RunLengthEncodeOutputStream extends FilterOutputStream | |||||
implements Finalizable { | |||||
private static final int MAX_SEQUENCE_COUNT = 127; | |||||
private static final int END_OF_DATA = 128; | |||||
private static final int BYTE_MAX = 256; | |||||
private static final int NOT_IDENTIFY_SEQUENCE = 0; | |||||
private static final int START_SEQUENCE = 1; | |||||
private static final int IN_SEQUENCE = 2; | |||||
private static final int NOT_IN_SEQUENCE = 3; | |||||
private int runCount = 0; | |||||
private int isSequence = NOT_IDENTIFY_SEQUENCE; | |||||
private byte[] runBuffer = new byte[MAX_SEQUENCE_COUNT + 1]; | |||||
/** @see java.io.FilterOutputStream **/ | |||||
public RunLengthEncodeOutputStream(OutputStream out) { | |||||
super(out); | |||||
} | |||||
/** @see java.io.FilterOutputStream **/ | |||||
public void write(byte b) | |||||
throws java.io.IOException { | |||||
runBuffer[runCount] = b; | |||||
switch (runCount) { | |||||
case 0: | |||||
runCount = 0; | |||||
isSequence = NOT_IDENTIFY_SEQUENCE; | |||||
runCount++; | |||||
break; | |||||
case 1: | |||||
if (runBuffer[runCount] != runBuffer[runCount - 1]) { | |||||
isSequence = NOT_IN_SEQUENCE; | |||||
} | |||||
runCount++; | |||||
break; | |||||
case 2: | |||||
if (runBuffer[runCount] != runBuffer[runCount - 1]) { | |||||
isSequence = NOT_IN_SEQUENCE; | |||||
} else { | |||||
if (isSequence == NOT_IN_SEQUENCE) { | |||||
isSequence = START_SEQUENCE; | |||||
} else { | |||||
isSequence = IN_SEQUENCE; | |||||
} | |||||
} | |||||
runCount++; | |||||
break; | |||||
case MAX_SEQUENCE_COUNT: | |||||
if (isSequence == IN_SEQUENCE) { | |||||
out.write(BYTE_MAX - (MAX_SEQUENCE_COUNT - 1)); | |||||
out.write(runBuffer[runCount - 1]); | |||||
runBuffer[0] = runBuffer[runCount]; | |||||
runCount = 1; | |||||
} else { | |||||
out.write(MAX_SEQUENCE_COUNT); | |||||
out.write(runBuffer, 0, runCount + 1); | |||||
runCount = 0; | |||||
} | |||||
isSequence = NOT_IDENTIFY_SEQUENCE; | |||||
break; | |||||
default: | |||||
switch (isSequence) { | |||||
case IN_SEQUENCE: | |||||
if (runBuffer[runCount] != runBuffer[runCount - 1]) { | |||||
out.write(BYTE_MAX - (runCount - 1)); | |||||
out.write(runBuffer[runCount - 1]); | |||||
runBuffer[0] = runBuffer[runCount]; | |||||
runCount = 1; | |||||
isSequence = NOT_IDENTIFY_SEQUENCE; | |||||
break; | |||||
} | |||||
runCount++; | |||||
break; | |||||
case NOT_IN_SEQUENCE: | |||||
if (runBuffer[runCount] == runBuffer[runCount - 1]) { | |||||
isSequence = START_SEQUENCE; | |||||
} | |||||
runCount++; | |||||
break; | |||||
case START_SEQUENCE: | |||||
if (runBuffer[runCount] == runBuffer[runCount - 1]) { | |||||
out.write(runCount - 3); | |||||
out.write(runBuffer, 0, runCount - 2); | |||||
runBuffer[0] = runBuffer[runCount]; | |||||
runBuffer[1] = runBuffer[runCount]; | |||||
runBuffer[2] = runBuffer[runCount]; | |||||
runCount = 3; | |||||
isSequence = IN_SEQUENCE; | |||||
break; | |||||
} else { | |||||
isSequence = NOT_IN_SEQUENCE; | |||||
runCount++; | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
/** @see java.io.FilterOutputStream **/ | |||||
public void write(byte[] b) | |||||
throws IOException { | |||||
for (int i = 0; i < b.length; i++) { | |||||
this.write(b[i]); | |||||
} | |||||
} | |||||
/** @see java.io.FilterOutputStream **/ | |||||
public void write(byte[] b, int off, int len) | |||||
throws IOException { | |||||
for (int i = 0; i < len; i++) { | |||||
this.write(b[off + i]); | |||||
} | |||||
} | |||||
/** @see Finalizable **/ | |||||
public void finalizeStream() | |||||
throws IOException { | |||||
switch (isSequence) { | |||||
case IN_SEQUENCE: | |||||
out.write(BYTE_MAX - (runCount - 1)); | |||||
out.write(runBuffer[runCount - 1]); | |||||
break; | |||||
default: | |||||
out.write(runCount - 1); | |||||
out.write(runBuffer, 0, runCount); | |||||
} | |||||
out.write(END_OF_DATA); | |||||
flush(); | |||||
if (out instanceof Finalizable) { | |||||
((Finalizable) out).finalizeStream(); | |||||
} | |||||
} | |||||
/** @see java.io.FilterOutputStream **/ | |||||
public void close() | |||||
throws IOException { | |||||
finalizeStream(); | |||||
super.close(); | |||||
} | |||||
} | |||||
/* | |||||
* 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.util; | |||||
import java.io.BufferedReader; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import java.io.InputStreamReader; | |||||
import java.io.Reader; | |||||
import java.util.Enumeration; | |||||
import java.util.Iterator; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
//code stolen from org.apache.batik.util and modified slightly | |||||
//does what sun.misc.Service probably does, but it cannot be relied on. | |||||
//hopefully will be part of standard jdk sometime. | |||||
/** | |||||
* This class loads services present in the class path. | |||||
*/ | |||||
public class Service { | |||||
private static Map providerMap = new java.util.Hashtable(); | |||||
public static synchronized Iterator providers(Class cls) { | |||||
ClassLoader cl = cls.getClassLoader(); | |||||
// null if loaded by bootstrap class loader | |||||
if (cl == null) { | |||||
cl = ClassLoader.getSystemClassLoader(); | |||||
} | |||||
String serviceFile = "META-INF/services/" + cls.getName(); | |||||
// log.debug("File: " + serviceFile); | |||||
List lst = (List)providerMap.get(serviceFile); | |||||
if (lst != null) { | |||||
return lst.iterator(); | |||||
} | |||||
lst = new java.util.Vector(); | |||||
providerMap.put(serviceFile, lst); | |||||
Enumeration e; | |||||
try { | |||||
e = cl.getResources(serviceFile); | |||||
} catch (IOException ioe) { | |||||
return lst.iterator(); | |||||
} | |||||
while (e.hasMoreElements()) { | |||||
try { | |||||
java.net.URL u = (java.net.URL)e.nextElement(); | |||||
//log.debug("URL: " + u); | |||||
InputStream is = u.openStream(); | |||||
Reader r = new InputStreamReader(is, "UTF-8"); | |||||
BufferedReader br = new BufferedReader(r); | |||||
String line = br.readLine(); | |||||
while (line != null) { | |||||
try { | |||||
// First strip any comment... | |||||
int idx = line.indexOf('#'); | |||||
if (idx != -1) { | |||||
line = line.substring(0, idx); | |||||
} | |||||
// Trim whitespace. | |||||
line = line.trim(); | |||||
// If nothing left then loop around... | |||||
if (line.length() == 0) { | |||||
line = br.readLine(); | |||||
continue; | |||||
} | |||||
// log.debug("Line: " + line); | |||||
// Try and load the class | |||||
// Object obj = cl.loadClass(line).newInstance(); | |||||
// stick it into our vector... | |||||
lst.add(line); | |||||
} catch (Exception ex) { | |||||
// Just try the next line | |||||
} | |||||
line = br.readLine(); | |||||
} | |||||
} catch (Exception ex) { | |||||
// Just try the next file... | |||||
} | |||||
} | |||||
return lst.iterator(); | |||||
} | |||||
} |
/* | |||||
* Copyright 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.util; | |||||
import java.io.FilterInputStream; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
/** | |||||
* This class is a FilterInputStream descendant that reads from an underlying InputStream | |||||
* up to a defined number of bytes or the end of the underlying stream. Closing this InputStream | |||||
* will not result in the underlying InputStream to be closed, too. | |||||
* <p> | |||||
* This InputStream can be used to read chunks from a larger file of which the length is | |||||
* known in advance. | |||||
*/ | |||||
public class SubInputStream extends FilterInputStream { | |||||
/** Indicates the number of bytes remaning to be read from the underlying InputStream. */ | |||||
private long bytesToRead; | |||||
/** | |||||
* Creates a new SubInputStream. | |||||
* @param in the InputStream to read from | |||||
* @param maxLen the maximum number of bytes to read from the underlying InputStream until | |||||
* the end-of-file is signalled. | |||||
*/ | |||||
public SubInputStream(InputStream in, long maxLen) { | |||||
super(in); | |||||
this.bytesToRead = maxLen; | |||||
} | |||||
/** @see java.io.InputStream#read() */ | |||||
public int read() throws IOException { | |||||
if (bytesToRead > 0) { | |||||
int result = super.read(); | |||||
if (result <= 0) { | |||||
bytesToRead--; | |||||
return result; | |||||
} else { | |||||
return -1; | |||||
} | |||||
} else { | |||||
return -1; | |||||
} | |||||
} | |||||
/** @see java.io.InputStream#read(byte[], int, int) */ | |||||
public int read(byte[] b, int off, int len) throws IOException { | |||||
if (bytesToRead == 0) { | |||||
return -1; | |||||
} | |||||
int effRead = (int)Math.min(bytesToRead, len); | |||||
//cast to int is safe because len can never be bigger than Integer.MAX_VALUE | |||||
int result = super.read(b, off, effRead); | |||||
if (result >= 0) { | |||||
bytesToRead -= result; | |||||
} | |||||
return result; | |||||
} | |||||
/** @see java.io.InputStream#skip(long) */ | |||||
public long skip(long n) throws IOException { | |||||
long effRead = Math.min(bytesToRead, n); | |||||
long result = super.skip(effRead); | |||||
bytesToRead -= result; | |||||
return result; | |||||
} | |||||
/** @see java.io.InputStream#close() */ | |||||
public void close() throws IOException { | |||||
//Don't close the underlying InputStream!!! | |||||
this.bytesToRead = 0; | |||||
} | |||||
} |
import org.apache.fop.traits.BorderPropsTestCase; | import org.apache.fop.traits.BorderPropsTestCase; | ||||
import org.apache.fop.traits.TraitColorTestCase; | import org.apache.fop.traits.TraitColorTestCase; | ||||
import org.apache.fop.util.ASCII85InputStreamTestCase; | |||||
import org.apache.fop.util.ASCII85OutputStreamTestCase; | |||||
import org.apache.fop.util.PDFNumberTestCase; | import org.apache.fop.util.PDFNumberTestCase; | ||||
import junit.framework.Test; | import junit.framework.Test; | ||||
TestSuite suite = new TestSuite( | TestSuite suite = new TestSuite( | ||||
"Test suite for FOP's utility classes"); | "Test suite for FOP's utility classes"); | ||||
//$JUnit-BEGIN$ | //$JUnit-BEGIN$ | ||||
suite.addTest(new TestSuite(ASCII85OutputStreamTestCase.class)); | |||||
suite.addTest(new TestSuite(ASCII85InputStreamTestCase.class)); | |||||
suite.addTest(new TestSuite(PDFNumberTestCase.class)); | suite.addTest(new TestSuite(PDFNumberTestCase.class)); | ||||
suite.addTest(new TestSuite(TraitColorTestCase.class)); | suite.addTest(new TestSuite(TraitColorTestCase.class)); | ||||
suite.addTest(new TestSuite(BorderPropsTestCase.class)); | suite.addTest(new TestSuite(BorderPropsTestCase.class)); |
/* | |||||
* 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.util; | |||||
import java.io.ByteArrayInputStream; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import org.apache.commons.io.IOUtils; | |||||
import org.apache.commons.io.output.ByteArrayOutputStream; | |||||
import org.apache.fop.pdf.PDFText; | |||||
import junit.framework.TestCase; | |||||
/** | |||||
* Test case for ASCII85InputStream. | |||||
* <p> | |||||
* ATTENTION: Some of the tests here depend on the correct behaviour of | |||||
* ASCII85OutputStream. If something fails here make sure | |||||
* ASCII85OutputStreamTestCase runs! | |||||
*/ | |||||
public class ASCII85InputStreamTestCase extends TestCase { | |||||
private static final boolean DEBUG = false; | |||||
/** | |||||
* @see junit.framework.TestCase#TestCase(String) | |||||
*/ | |||||
public ASCII85InputStreamTestCase(String name) { | |||||
super(name); | |||||
} | |||||
private byte[] decode(String text) throws Exception { | |||||
byte[] ascii85 = text.getBytes("US-ASCII"); | |||||
InputStream in = new ByteArrayInputStream(ascii85); | |||||
InputStream decoder = new ASCII85InputStream(in); | |||||
return IOUtils.toByteArray(decoder); | |||||
} | |||||
private byte[] getChunk(int count) { | |||||
byte[] buf = new byte[count]; | |||||
System.arraycopy(ASCII85OutputStreamTestCase.DATA, 0, buf, 0, buf.length); | |||||
return buf; | |||||
} | |||||
private String encode(byte[] data, int len) throws Exception { | |||||
ByteArrayOutputStream baout = new ByteArrayOutputStream(); | |||||
java.io.OutputStream out = new ASCII85OutputStream(baout); | |||||
out.write(data, 0, len); | |||||
out.close(); | |||||
return new String(baout.toByteArray(), "US-ASCII"); | |||||
} | |||||
private void innerTestDecode(byte[] data) throws Exception { | |||||
String encoded = encode(data, data.length); | |||||
if (DEBUG) { | |||||
if (data[0] == 0) { | |||||
System.out.println("self-encode: " + data.length + " chunk 000102030405..."); | |||||
} else { | |||||
System.out.println("self-encode: " + new String(data, "US-ASCII") | |||||
+ " " + PDFText.toHex(data)); | |||||
} | |||||
System.out.println(" ---> " + encoded); | |||||
} | |||||
byte[] decoded = decode(encoded); | |||||
if (DEBUG) { | |||||
if (data[0] == 0) { | |||||
System.out.println("decoded: " + data.length + " chunk 000102030405..."); | |||||
} else { | |||||
System.out.println("decoded: " + new String(decoded, "US-ASCII") | |||||
+ " " + PDFText.toHex(decoded)); | |||||
} | |||||
} | |||||
assertEquals(PDFText.toHex(data), PDFText.toHex(decoded)); | |||||
} | |||||
/** | |||||
* Tests the output of ASCII85. | |||||
* @throws Exception if an error occurs | |||||
*/ | |||||
public void testDecode() throws Exception { | |||||
byte[] buf; | |||||
innerTestDecode("1. Bodypart".getBytes("US-ASCII")); | |||||
if (DEBUG) { | |||||
System.out.println("==========================================="); | |||||
} | |||||
innerTestDecode(getChunk(1)); | |||||
innerTestDecode(getChunk(2)); | |||||
innerTestDecode(getChunk(3)); | |||||
innerTestDecode(getChunk(4)); | |||||
innerTestDecode(getChunk(5)); | |||||
if (DEBUG) { | |||||
System.out.println("==========================================="); | |||||
} | |||||
innerTestDecode(getChunk(10)); | |||||
innerTestDecode(getChunk(62)); | |||||
innerTestDecode(getChunk(63)); | |||||
innerTestDecode(getChunk(64)); | |||||
innerTestDecode(getChunk(65)); | |||||
if (DEBUG) { | |||||
System.out.println("==========================================="); | |||||
} | |||||
String sz; | |||||
sz = PDFText.toHex(decode("zz~>")); | |||||
assertEquals(PDFText.toHex(new byte[] {0, 0, 0, 0, 0, 0, 0, 0}), sz); | |||||
sz = PDFText.toHex(decode("z\t \0z\n~>")); | |||||
assertEquals(PDFText.toHex(new byte[] {0, 0, 0, 0, 0, 0, 0, 0}), sz); | |||||
if (DEBUG) { | |||||
System.out.println("==========================================="); | |||||
} | |||||
try { | |||||
decode("vz~>"); | |||||
fail("Illegal character should be detected"); | |||||
} catch (IOException ioe) { | |||||
//expected | |||||
} | |||||
/* DISABLED because of try/catch in InputStream.read(byte[], int, int). | |||||
* Only the exception happening on the first byte in a block is being | |||||
* reported. BUG in JDK??? | |||||
* | |||||
try { | |||||
decode("zv~>"); | |||||
fail("Illegal character should be detected"); | |||||
} catch (IOException ioe) { | |||||
//expected | |||||
}*/ | |||||
} | |||||
private byte[] getFullASCIIRange() { | |||||
java.io.ByteArrayOutputStream baout = new java.io.ByteArrayOutputStream(256); | |||||
for (int i = 254; i < 256; i++) { | |||||
baout.write(i); | |||||
} | |||||
return baout.toByteArray(); | |||||
} | |||||
/** | |||||
* Tests the full 8-bit ASCII range. | |||||
* @throws Exception if an error occurs | |||||
*/ | |||||
public void testFullASCIIRange() throws Exception { | |||||
innerTestDecode(getFullASCIIRange()); | |||||
} | |||||
} |
/* | |||||
* Copyright 1999-2004 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. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.util; | |||||
import java.io.OutputStream; | |||||
import org.apache.commons.io.output.ByteArrayOutputStream; | |||||
import junit.framework.TestCase; | |||||
/** | |||||
* Test case for ASCII85OutputStream | |||||
* | |||||
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> | |||||
*/ | |||||
public class ASCII85OutputStreamTestCase extends TestCase { | |||||
/** Test data */ | |||||
public static final byte[] DATA = new byte[100]; | |||||
static { | |||||
//Fill in some data | |||||
for (int i = 0; i < 100; i++) { | |||||
DATA[i] = (byte)i; | |||||
} | |||||
} | |||||
/** | |||||
* @see junit.framework.TestCase#TestCase(String) | |||||
*/ | |||||
public ASCII85OutputStreamTestCase(String name) { | |||||
super(name); | |||||
} | |||||
private String encode(int count) throws Exception { | |||||
return encode(DATA, count); | |||||
} | |||||
private String encode(byte[] data, int len) throws Exception { | |||||
ByteArrayOutputStream baout = new ByteArrayOutputStream(); | |||||
OutputStream out = new ASCII85OutputStream(baout); | |||||
out.write(data, 0, len); | |||||
out.close(); | |||||
return new String(baout.toByteArray(), "US-ASCII"); | |||||
} | |||||
/** | |||||
* Tests the output of ASCII85. | |||||
* @throws Exception if an error occurs | |||||
*/ | |||||
public void testOutput() throws Exception { | |||||
String sz = encode(new byte[] {0, 0, 0, 0, 0, 0, 0, 0}, 8); | |||||
assertEquals("zz~>", sz); | |||||
String s3 = encode(3); | |||||
//System.out.println(">>>" + s3 + "<<<"); | |||||
assertEquals("!!*-~>", s3); | |||||
String s10 = encode(10); | |||||
//System.out.println(">>>" + s10 + "<<<"); | |||||
assertEquals("!!*-'\"9eu7#RL~>", s10); | |||||
String s62 = encode(62); | |||||
//System.out.println(">>>" + s62 + "<<<"); | |||||
assertEquals("!!*-'\"9eu7#RLhG$k3[W&.oNg'GVB\"(`=52*$$(B+<_pR," | |||||
+ "UFcb-n-Vr/1iJ-0JP==1c70M3&s#]4?W~>", s62); | |||||
String s63 = encode(63); | |||||
//System.out.println(">>>" + s63 + "<<<"); | |||||
assertEquals("!!*-'\"9eu7#RLhG$k3[W&.oNg'GVB\"(`=52*$$(B+<_pR," | |||||
+ "UFcb-n-Vr/1iJ-0JP==1c70M3&s#]4?Yk\n~>", s63); | |||||
String s64 = encode(64); | |||||
//System.out.println(">>>" + s64 + "<<<"); | |||||
assertEquals("!!*-'\"9eu7#RLhG$k3[W&.oNg'GVB\"(`=52*$$(B+<_pR," | |||||
+ "UFcb-n-Vr/1iJ-0JP==1c70M3&s#]4?Ykm\n~>", s64); | |||||
String s65 = encode(65); | |||||
//System.out.println(">>>" + s65 + "<<<"); | |||||
assertEquals("!!*-'\"9eu7#RLhG$k3[W&.oNg'GVB\"(`=52*$$(B+<_pR," | |||||
+ "UFcb-n-Vr/1iJ-0JP==1c70M3&s#]4?Ykm\n5Q~>", s65); | |||||
} | |||||
} |