The Java JODG library provides support for generation of flat ODG files for use with vector-based graphics programs such as LibreOffice Draw, using standard Java AWT Graphics “draw” and “fill” commands. The library provides a special Graphics2D subclass, ODGGraphics, that renders draw commands into flat ODG (.fodg) XML syntax. A sequence of standard Java Graphics drawing method calls on an ODGGraphics instance can thus create a flat ODG XML document that, when opened with a vector graphics drawing program such as LibreOffice, will display the Java image as an image that can be modified within the drawing program. The output is intended to be compliant with the OASIS Open Document Format.
This library is released under the MIT License.
Basic Workflow
The class ODGGraphics implements the graphics operations defined by the standard Java Graphics2D class. To create an ODG drawing, you use the standard Java Graphics drawing calls (including drawing, transformations, etc.) on an instance of ODGGraphics. The ODGGraphics instance will encode these Java drawing commands as ODG XML entities in an associated ODGDocument, which can then be retrieved as a text string and saved in a flat ODG (.fodg) file.
An ODGGraphics is associated with an ODGDocument. The basic workflow is:
/* Create an ODG document and get its associated ODGGraphics instance */ ODGDocument odgDocument = new ODGDocument(); ODGGraphics odgGraphics = odgDocument.getGraphics(); /* Do drawing commands as on any other Graphics. If you have a paint(Graphics) method, you can just use it with the ODGGraphics instance since it's a subclass of Graphics. */ paint(odgGraphics); /* Get the ODG output as a string - it's just text - and save in a flat ODG file (.fodg) for use with a vector drawing program such as LibreOffice Draw */ String odgText = odgDocument.toODGString(); String filePath = “path/to/file.fodg”; FileWriter fileWriter = new FileWriter(filePath); fileWriter.write(odgText); fileWriter.flush(); fileWriter.close(); /* For drawing, just use standard Java drawing operations */ public void paint(Graphics graphics) { // set pen characteristics graphics.setColor(Color.RED); graphics.setStroke(new BasicStroke(3)); // draw stuff - line, rectangles, ovals, ... graphics.drawLine(0, 0, 1000, 500); graphics.drawRect(1000, 500, 150, 150); graphics.drawRoundRect(20, 200, 130, 100, 20, 10); graphics.drawOval(200, 800, 200, 400); graphics.drawArc(100, 1900, 400, 200, 60, 150); // can draw filled shapes, which get // implemented as ODG hatches graphics.setColor(Color.BLUE); graphics.fillRect(100, 100, 100, 50); int[] xPoints = {200, 300, 250}; int[] yPoints = {200, 250, 300}; graphics.fillPolygon(xPoints, yPoints, xPoints.length); // text too graphics.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 38)); graphics.drawString("Some 38-point monospaced blue text at position 480, 400", 480, 400); // and even transformations, though there are // some caveats - the shear and scale // operations aren't correctly implemented // in LibreOffice Draw through version 6.3 // (see caveats below) graphics.rotate(Math.PI/4); graphics.drawRect(100, 100, 200, 200); }
Features
The JODG library provides most of the drawing operations available in the standard Java Graphics and Graphics2D classes. However, certain methods are unimplemented at present (some due to lack of support in ODG). These unimplemented operations will be ignored or throw an UnsupportedOperationException if used, as indicated below. Some additional features currently have no or limited support, as indicated below.
Supported operations
- Drawing operations, including
- drawLine, drawPolyline
- drawPolygon, fillPolygon
- drawArc, fillArc
- drawOval, fillOval
- drawRect, fillRect, clearRect
- drawRoundRect, fillRoundRect
- draw(Shape), fill(Shape), clear(Shape)
- Text operations
- drawString, drawChars, drawBytes
- registerFont
- Drawing properties
- Color
- Line width
- Font properties: serif/sans-serif, size, bold, italic
- Affine transformation operations
- scale (see caveat regarding LibreOffice)
- shear (see caveat regarding LibreOffice)
- translate
- rotate
Not supported
- Image drawing – throws UnsupportedOperationException
- Paint xfermodes – Ignored
- Clipping, including clipRect, clipRegion, clipPath, etc. – Ignored
Caveats
Transformations
Current versions of LibreOffice Draw incorrectly render some shapes under certain transformations. In particular, transformations that include a shear (skew) component are incorrectly handled, and thus the ODG representation of shapes under such transformations in LibreOffice will not match the images created in Java. Additionally, paths and polylines/polygons are not correctly represented in LibreOffice under scaling transformations. The above applies at least to LibreOffice version 6.3 and earlier. for more information, see:
- https://bugs.documentfoundation.org/show_bug.cgi?id=98584
- https://bugs.documentfoundation.org/show_bug.cgi?id=98565
To work around these limitations, the JODG library provides a setting in ODGDoument, preApplyTransforms(boolean), that when set to true will pre-apply Java transformations to shapes and generate the equivalent ODG for the transformed shapes. This (for the most part) relieves the ODG draw package from the need to apply transformations. (The exception concerns ellipses – when the major and minor axes aren’t parallel to the x and y axes, these need to have a rotation and translation associated since the ODG ellipse definition only supports horizontal and vertical major and minor axes. Fortunately LibreOffice seems to handle these transforms correctly.)
One disadvantage of pre-applying transforms is that certain shapes will be mapped to different (more general) shapes – for example, circles may become ellipses, and rectangles may become general polygons. Thus unless Java transforms are being used and causing problems in the ODG draw program, it is best to leave this set to false, the default. If you’re using only rotations and translations, there shouldn’t be issues with leaving this switch set to false, as LibreOffice seems to handle these transforms correctly.
Text Frames and Fonts
The fonts used for rendering onscreen in Java and those used in ODG viewers such as LibreOffice Draw will generally not be identical, even for fonts with the same name and size – there will often be very slight differences in geometry that cause letters to have slightly different widths. This can be an issue when a string is enclosed in a text frame, as is the case in ODG files. If the text frame is correctly sized to fit the Java text snugly, the string rendered in the ODG viewer may not quite fit if the ODG font is slightly wider. This will cause the string to be split into two lines if it hits the right edge of the text frame. To prevent this, the text frames can be set to be generated slightly larger than needed for the Java fonts. The default in the JODG package is to make the frames 5% wider than needed to give a little extra room in case the ODG font is wider. The factor used for this text box expansion can be set through the ODGDocument method setTextFrameExpansionFactor(double). Note that making the text box slightly larger than needed will be invisible in the generated ODG; it will only be noticeable when you edit the ODG text.
Example ODG Files
Some example files generated with JODG are at the links below. The Java source code used to generate these through the JODG Library is available in the Example Code section.
Example Code
A test project is available that illustrates how to use the library and that can also be used to test its functionality. The class JODGTestPanel illustrates the use of the JODGGraphics class and its draw methods.
Documentation
Downloads
The downloads are supplied as zipped archives; the library archive contains the compiled jodg.jar file for inclusion in a project, while the source archive contains the Java source files that can be used to rebuild the .jar file or included as source files in a referencing project. The test app source contains source for a simple test app that uses the classes in the JODG library.
Version |
Library (.jar) |
Source |
Test App Source |
1.0 | jodg_lib_v1.0.zip | jodg_src_v1.0.zip | jodg_test_v1.0.zip |
Revision History
Version |
Date | Changes |
1.0 | 2023-02-22 | Initial release |
Notes