Java Vector Cut and Paste Library
This is the home page for the Java Library JVectCutAndPaste. This library provides :
- writing support for a number of Vector formats (WMF, EMF, MacPict, EPS), which can be used with Graphics2D.
- a simple class for copying vector images on the clipboard. Those images can be pasted in most word processors.
The java cut and paste library probably suffers from the "good enough for me" syndrom. That is, I did not try to support all graphic features (in particular as far as colour transparency and filling are concerned), but only those I needed. If you want more, feel free to contribute code. So limitations are:
- no transparency nor gradient fill. Just plain colour fill, which is reasonable for diagrams (or in my case for hieroglyphs).
- actual rendering depends on the target graphic format. EMF produces better results than MAC PICT or WMF, for instance (it can handle complex shapes with holes in them). As a rule, I prefer losing some features than getting a bitmap (the solution chosen by java for printing).
- no support for bitmap pictures yet. This is probably not too difficult to add, and would be a good candidate for an external contribution.
Getting the source : the current distribution of the library is part of JSesh. Get the whole sources for JSesh:
hg clone http://jsesh.hg.sourceforge.net:8000/hgroot/jsesh/jsesh
The sources for this particular library are in the folder jvectClipboard.
Note that there are other libraries for vector graphics. If you need more complete capabilities, you might have a look at freeHep. When I started the JSesh project, it didn't provide all functionnalities I needed, hence the creation of this library. Now, I haven't tried it yet, but the current version of FreeHep also provides clipboard capabilities (but it probably only works on Windows).
Trying it
(deprecated. I must provide a maven-compatible system).
Get the source distribution, and type "ant run".
You will see a small window with a "copy" button. Click. Then open your favourite text editor (Word, OpenOffice, Mellel...).
Type "paste", and lo, a nice red rectangle was pasted!
License and the like
This library is distributed under the LGPL (the GNU lesser public license), because I want it to be usable, including in commercial softwares. PDF copy/paste is done using an old version of IText, because of licenses issues (version 2.1.5 was still under the LGPL).
Using the library for creating vector graphics
The various Graphics2D object provided (for WMF, EMF, MACPICT, EPS, SVG...) are relatively easy to use. Please notice that I made them for a specific software, JSesh, which might mean they lack some features you need. In particular, I didn't bother to emulate transparency and the like.
Currently, text is rendered as drawing outlines which means that :
- it will render reasonably well
- but the graphical file will be large, as the text is rendered as a drawing.
Pasting vector graphics
Introduction
Vector graphics are often difficult to copy on the clipboard. In fact, on Windows, it used to be impossible without using native code, as one had to send the address of the vector graphics.
This is why this system uses a trick (I'm not really sure how I decided to use it. I think a blog about Freemind gave me the idea. However, I haven't seen any free Java software which performed vector cut and paste (and on all platforms).
The trick is that the vector graphic is embedded in RTF. And Java can copy RTF on the clipboard without any problem. That's the good news.
Now, for the bad news:
- RTF only support three formats: MACPICT, EMF and WMF. None of them support transparency, or CMYK colors.
- RTF can be pasted without problem in a word processor. It works great with Word or Openoffice Writer. However, it doesn't work in PowerPoint, for instance.
- At least on the Mac, the latest versions of Word do not paste RTF containing graphics any more (...) but you can use PDF in this case.
With recent versions of Java, things have improved, and some formats can be cut and pasted natively. For instance, PDF on Mac OS X, and EMF on Windows.
Simple case
You can have a look at JVectClipboardTest for a simple example.
Basically, using the library is as simple as :
// creating a SimpleGraphicsObject. The size is expressed in points.
SimpleClipGraphics clipGraphics = new SimpleClipGraphics(300, 200);
// get the graphics object. The unit used is 1 unit = 1 point.
Graphics2D g = clipGraphics.getGraphics();
// Draw...
g.setColor(Color.RED);
g.fill(new Rectangle2D.Double(30, 30, 100, 100));
// Dispose the graphics object...
g.dispose();
// Send it to the clipboard
clipGraphics.copyToClipboard();
And that's all.
You might want to choose the format used for the embedded vector pictures. This is done by calling setPictureFormat before you call getGraphics. The default format used is MACPICT.
SimpleClipGraphics clipGraphics = new SimpleClipGraphics(300, 200);
clipGraphics.setPictureFormat(PictureFormat.EMF);
Graphics2D g = clipGraphics.getGraphics();
How should you choose the format? Well:
- MACPICT: renders well on all platforms. The format is somehow limited (basically, it doesn't use curves, nor transparency, and coordinates are 16bits).
- WMF: renders well on windows, and more or less correctly on Mac OS X. The format is somehow limited (basically, it doesn't use curves, nor transparency, and coordinates are 16bits).
- EMF: gives great results with OpenOffice/Neooffice writer on all platforms. Renders well on M/S Windows with most word processors softwares. Doesn't render correctly on Mac OS X (except with OpenOffice/Neooffice). The format is more or less equivalent to PS or PDF. It doesn't handle transparency.
- DIRECT_EMF: on Windows only. Has the advantage over embedded EMF that it is a real graphic format, not a trick using rich text. So it should work with most softwares, including those that don't understand RTF well enough (read : anything but word processors). So, DIRECT_EMF should work with powerpoint for instance.
- PDF: gives the best possible rendering, but only work with Mac OS X (and then, with the Mac OS X application which accept PDF copy/paste, for instance: mellel, Word 2008 (not Word 2004), and Apple softwares in general.
Of course, if you use curves in your drawing, you will get a reasonable approximation with MACPICT and WMF. But the EMF picture will be better.
More complex cases
In more complex cases, you want to propose a number of different formats on the clipboard.
Then, the solution is usually to create your own Transferable class. This class will contain the original data which generates the picture, and propose it in various "flavors".
Your code will be something like :
public class MyTransferable implements Transferable {
public static final DataFlavor RTF_FLAVOR = new DataFlavor("text/rtf", null);
private static final DataFlavor[] flavors= {RTF_FLAVOR, DataFlavor.stringFlavor};
private SomeObject objectToPaste;
public RTFTransferable(RTFPicture rtfPicture) {
this.rtfPicture= rtfPicture;
}
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
if (RTF_FLAVOR.equals(flavor)) {
EMFPicture pict= new EMFPicture(.....); // use the appropriate size for your data....
Graphics2D g= pict.getGraphics();
// draw on g what you want to draw...
...
g.dispose();
return new ByteArrayInputStream(RTFPictureUtils
.createRTFByteArray(pict));
} else if (DataFlavor.stringFlavor.equals(flavor)) {
return objectToPaste.toString();
} else {
throw new UnsupportedFlavorException(flavor);
}
}
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
DataFlavor[] flavors = getTransferDataFlavors();
for (int i = 0; i < flavors.length; i++) {
if (flavors[i].equals(flavor)) {
return true;
}
}
return false;
}
}
Of course, this is simply a technical example. I suggest to isolate the drawing code in another class.
Not using the library
If your target is a Mac, you might consider pasting PDF on the clipboard. PDF works great with most "real" Mac softwares, like Mellel. Word 2008 also support PDF (which is a good move). Now, of course, embedded PDF will be somehow problematic if you want to share your file with someone running windows. You can use IText to produce PDF.
To do this, you need to create a Transferable object which handle the PDF flavour. The DataFlavor to use is:
public static final DataFlavor PDFFlavor = new DataFlavor(
"application/pdf", null);
I might write a longer explanation later, with a short example. If you are interested, you may look at the JSesh code.
A useful utility
If you need to experiment and try to see what java can copy or paste, I have writen for my own tests a small class called TransfertTest
It's stand-alone. Just get and compile. It allows you to inspect the clipboard, and try to copy or paste stuff.