Apache XML Graphics Commons
| Language | Java |
|---|---|
| License | Apache-2.0 |
| Repository | github.com/apache/xmlgraphics-commons |
| Documentation | PostScript and EPS support |
| Depends on | commons-logging |
| Read / write | DSC comments only (no rendering) / yes (EPS, Level 2) |
XML Graphics Commons is the graphics toolkit behind Apache FOP and Batik. EPSDocumentGraphics2D is a Graphics2D implementation: you draw with normal Java2D calls and it writes a single-page, fully conforming EPS file with %%BoundingBox. The DSC parser reads the header comments of existing EPS and PostScript files without running them.
It can’t render EPS and doesn’t add a preview image. Transparency in Java2D drawing is not reproduced, because PostScript has none.
Installation#
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>xmlgraphics-commons</artifactId>
<version>2.11</version>
</dependency>
Gradle: implementation("org.apache.xmlgraphics:xmlgraphics-commons:2.11")
Basic usage: write an EPS file with Java2D#
import java.awt.Color;
import java.awt.Font;
import java.awt.geom.Ellipse2D;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.xmlgraphics.java2d.GraphicContext;
import org.apache.xmlgraphics.java2d.ps.EPSDocumentGraphics2D;
public class WriteEps {
public static void main(String[] args) throws IOException {
try (OutputStream out = new BufferedOutputStream(new FileOutputStream("logo.eps"))) {
EPSDocumentGraphics2D g2d = new EPSDocumentGraphics2D(true); // text as shapes
g2d.setGraphicContext(new GraphicContext());
g2d.setupDocument(out, 200, 100); // bounding box size in points
g2d.setColor(new Color(50, 100, 200));
g2d.fill(new Ellipse2D.Double(10, 10, 80, 80));
g2d.setColor(Color.BLACK);
g2d.setFont(new Font("SansSerif", Font.BOLD, 28));
g2d.drawString("LOGO", 100, 62);
g2d.finish();
}
}
}
How to read the bounding box of an EPS file#
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import org.apache.xmlgraphics.ps.DSCConstants;
import org.apache.xmlgraphics.ps.dsc.DSCParser;
import org.apache.xmlgraphics.ps.dsc.events.DSCComment;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentBoundingBox;
try (InputStream in = new BufferedInputStream(new FileInputStream("logo.eps"))) {
DSCParser parser = new DSCParser(in); // needs a stream that supports mark()
DSCComment c = parser.nextDSCComment(DSCConstants.BBOX);
if (c instanceof DSCCommentBoundingBox bbox && bbox.getBoundingBox() != null) {
System.out.println(bbox.getBoundingBox()); // Rectangle2D in points
}
}
DSCConstants.HIRES_BBOX finds %%HiResBoundingBox.
How to read an EPS file that has a TIFF or WMF preview#
Files with a binary header start with C5 D0 D3 C6 instead of %!PS. Read the offset and length of the PostScript section (little-endian) and parse only that part:
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Path;
static InputStream postScriptPart(Path path) throws IOException {
byte[] data = Files.readAllBytes(path);
ByteBuffer b = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
if (data.length >= 30 && b.getInt(0) == 0xC6D3D0C5) {
int offset = b.getInt(4);
int length = b.getInt(8);
return new ByteArrayInputStream(data, offset, length);
}
return new ByteArrayInputStream(data); // plain EPS
}
Pass the result to new DSCParser(...). ByteArrayInputStream supports mark().
Tips#
EPSDocumentGraphics2D(false)writes text with the standard PostScript fonts (Helvetica, Times, Courier) instead of outlines: smaller files, but only Latin text and only those fonts.- To produce several EPS files from one drawing routine, write the routine against
Graphics2Dand pass it eitherEPSDocumentGraphics2Dor aBufferedImagegraphics for a PNG preview.