XML Europe 2001 logo21-25 May 2001
Internationales Congress Centrum (ICC)
Berlin, Germany

SVG Support in ILOG JViews Component Suite

Emmanuel Tissandier <etissandier@ilog.fr>
Christophe Jolif <cjolif@ilog.fr>
 PDF version    Latest version   

ABSTRACT

As part of the SVG Working Group, ILOG has implemented SVG in the ILOG JViews Component Suite: ILOG's Java two-dimensional graphic library. This paper explains the technical considerations when importing and exporting SVG documents from a two-dimensional graphic framework in Java. It also explains how the Java 2D API and Batik helps you doing this. We will also see how the export feature can be used to generate SVG on the server side to create thin client applications that include map displays or workflow and network diagrams. The benefits and limitations of this approach are also discussed.

Table of Contents

1. Introduction

ILOG has been developing the JViews Component Suite since 1997. JViews is an object-oriented library written in Java that targets developers with advanced needs in two-dimensional graphics. ILOG is a member of the SVG (Scalable Vector Graphics) Working Group in the W3C and has implemented SVG in the ILOG JViews Component Suite. Since 2000, ILOG has also been involved in the development of Batik an Apache project on SVG.

1.1. What is ILOG JViews Component Suite?

The ILOG JViews Component Suite is composed of several packages addressing different types of application problems:

The Graphics Framework package is the base of all the JViews packages. It consists of a Java library that defines classes such as rectangles, polylines, polygons, circles, text, and images. These objects are called "graphic objects". It also defines a Manager class—the data-structure that manages the graphic objects and allows fast selection, panning, and zooming.

The Maps package allows developers to create interfaces with custom screen objects on top of map data. The Maps package natively imports the most common raster and vector formats, and allows data from different sources to be combined seamlessly.

The Graph Layout package contains a broad set of algorithms for automatically rearranging diagram-like graphs to produce displays such as rings and star, bus-shaped layouts, hierarchical layouts, or radial layouts.

The Gantt Chart package provides complete support for viewing schedules—both resource and task oriented.

1.2. What is SVG?

SVG is a language for describing two-dimensional graphics in XML. SVG elements are used to describe objects such as rectangles, lines, polylines, polygons, text, paths (sets of lines and curves), and images. The SVG elements can be styled to change their graphic appearance (color, line width, and so on) and can be transformed, clipped, and manipulated in various ways.

1.3. What is Batik?

Batik is an SVG Java API developped at Apache and that is available at the following URL: http://xml.apache.org/batik. It provides a set of functionalities allowing to use SVG images for various purposes, such as viewing, generation or manipulation.

2. Importing SVG into ILOG JViews

There are two main reasons for adding SVG import feature to JViews. The first reason is interoperability. With SVG import added to the export facility, JViews is able to read documents built with other software and possibly modify them for external use. The second reason is that this feature allows end users to develop SVG-enabled applications with the library. This means that their web or desktop applications can display and edit SVG documents without coding effort.

Importing SVG into JViews has beeen done in three steps: create the graphic objects that match the SVG graphic elements, apply a style to these objects, and add these graphic objects to the JViews object manager to be able to display them on the screen. In the following sections we will see what have been the choices made when implementing SVG import in JViews and in the last section we will see how Batik API could be integrated in it.

2.1. Creating JViews graphics objects from SVG elements

SVG uses an XML grammar to describe its graphic elements. The SVG document must first be parsed and then the parsed elements must be mapped to JViews graphic objects.

2.1.1. Parsing an SVG file as an XML file

There are two ways of achieving the parsing. The first one is to parse the SVG file using a SAX parser and to create JViews graphic objects during the parsing in respond to SAX events.The second solution is to parse the SVG file using a DOM parser that creates a document tree, and then walk on the resulting tree of the document to create JViews graphic objects.

Although the DOM solution consumes more memory and may be slower because it requires two separate parsings, it has the advantage that it easily allows you to go back and forth within the document to reach elements referenced by the one currently being parsed. It is particularly useful to deal with forward references.

This is illustrated in the following example:

<svg> 
<use x="0" y="0" width="100" height="100" xlink:href="#ref"/> 
<!-- Many other elements -->
<rect id="s21-2ref" x="10" y="10" width="100" height="100"/>
</svg>

When creating JViews graphic objects directly during the SAX parsing, the 'rect' element with the 'ref' id is not yet available. With the DOM parser approach, we already have access to the entire tree when creating the graphic objects.

Moreover having the SVG elements in a memory tree structure similar to the DOM one is required to correctly apply CSS styling rule and as JViews doesn't have such a structure it is another good reason to go through a DOM parser that will create the structure.

That is why this solution has been chosen as the import feature for ILOG JViews.

2.1.2. Mapping the parsed elements

This section describes how SVG graphic elements can be mapped to JViews graphic objects. These graphic objects are drawn using Java 2D primitives.

1.2.1. Simple SVG graphics elements

For most SVG graphics elements the translation is very simple. For example SVG <polyline> objects are translated to the JViews IlvPolylinegraphic object that allows to draw and interact with a polyline in the JViews object manager:

<polyline points="0 0 64 48 100 100"/>

can be translated to the following Java code:

IlvPoint[] array = new IlvPoint[3];
array[0] = new IlvPoint(0, 0);
array[1] = new IlvPoint(64, 64);
array[2] = new IlvPoint(100, 100);
IlvGraphic object = new IlvPolyline(array);

Similar translations exist for <line>, <polygon>, <circle>, <ellipse>, <image>and <g>elements. These simple graphics elements only require simple AWT drawing primitives to be displayed.

1.2.2. The <text> element

A default SVG <text> element can be translated to a JViews IlvLabel graphic object using AWT Graphics.drawString()method to be drawn. However the SVG <text> element offers other possibilities not provided by Java 2D or the ILOG JViews 2D toolkit. For example, <text> objects can be drawn along an arbitrary path formed by other graphic elements. That is why we added to JViews graphic class called IlvTextPath that provides the same facilities as the <textpath> SVG elements.

1.2.3. The <path> element

The <path> element also has a counterpart in the JViews library: the IlvGeneralPath object. This object is based on the Java 2D java.awt.geom.GeneralPath object. Here is a simple example of how to create a Java 2D java.awt.geom.GeneralPath corresponding to an SVG <path>element:

<path d="M100 100L200200l10 50v10c210 260 180 310 130 300z"/>

can be translated to the following in Java 2D code:

GeneralPath path = new java.awt.geom.GeneralPath();
path.moveTo(100, 100);
path.lineTo(200, 200);
path.lineTo(200+10, 200+50);
path.lineTo(210, 250+10);
path.curveTo(210, 260, 180, 310, 130, 300);
path.closePath();

In this example, it appears that the Java 2D matches the <path>element perfectly. However, in some cases the grammar for defining SVG<path> elements does not exactly match the attributes necessary to build a Java 2D GeneralPath object. This is the case for arc segments for example. The start and end points and the ellipse radii define an SVG arc segment. Java 2D expects the following parameters to draw an arc segment: the center of the ellipse, the radii, the start angles, and the delta angles. This is why some computations are necessary for a correct translation. Fortunately, the equations are available in Appendix F of [SVG 1.0]

2.2. Applying a style to imported elements

The second step when importing an SVG file into JViews is to apply a style to the imported graphic elements.

Implementing styling is more difficult than simply importing graphic elements that are described in a pure XML grammar. In SVG, style can be defined with the CSS syntax instead of the XML syntax. That is why the first requirement for importing style is to have a CSS parser in the toolkit to read the CSS syntax. This is described first. Then, the styles that have been parsed are applied to the JViews objects using Java 2D.

2.2.1. Parsing style described with a CSS syntax

Just as a SAX API has been defined for parsing XML, the W3C is currently defining a SAC API for CSS parsers. As SAC implementations were not widespread when the JViews SVG import feature was developped, we implemented our own parser. However it could be replaced by the Batik CSS parser that is now available at Apache and that is SAC compliant.

Once read in the CSS style sheets, rule selectors returned by the parser must be compared to SVG elements to see if they match them. Finally, a cascade must be completed for each matching CSS rule to determine the final style of each SVG graphic element. These complex computations are described in [CSS 2]

2.2.2. Applying the style to the JViews objects using Java 2D

Once the style of a graphic element has been computed using the cascading mechanism, some style properties will be easy to apply to JViews graphic objects. This is the case for basic fill options such as the color and its transparency, basic stroke options such as the width of the stroke, the dash array, and the join and cap styles. JViews graphic objects already support these features thanks to the Java 2D API.

For example:

<path d="..." style="fill:red;fill-opacity:0.5;stroke:blue; 
  stroke-width:4;stroke-dasharray:2,4;stroke-linecap:round"/>

This SVG element will be styled using two java.awt.Paint objects and a java.awt.Stroke object.

Paint fillPaint = new Color(1f, 0f, 0f, 0.5f);
Paint strokePaint = Color.blue;
float[] dasharray = {2, 4};
Stroke stroke = new BasicStroke(4, BasicStroke.CAP_ROUND,
  BasicStroke.JOIN_MITER, 8, dasharray, 0);

And the Java 2D objects that are created above can be applied to the JViews IlvGeneralPath graphic object that allows to draw and interact with a generic shape in the object manager:

path.setFillPaint(fillPaint);
path.setStrokePaint(strokePaint);
path.setStroke(stroke);

More complex styling possibilities require extensions of the JViews toolkit or even extensions of Java 2D.

2.2.1. Extension of JViews Toolkit

Some styling properties have required an update of graphic objects to support already existing Java 2D features not already implemented in the toolkit. This is the case for clipping of graphic objects for example. In SVG, a graphic element can be clipped by another one. This feature is available in Java 2D but was not in the JViews toolkit. That's why it has been implemented by adding a setClip method on JViews graphic objects using the Java 2D API.

2.2.2. Extension of Java 2D

However, some other SVG possibilities such as the radial color gradients, the multiple color linear gradients, or the complex image filters are not present in Java 2D and thus cannot simply be added to the JViews objects.

This is one of the place where the Batik API may also help in implementing an SVG import feature in a 2D toolkit. JViews already integrates the radial and linear gradient from Batik and the same kind of integration could be done with Batik filter API.

2.3. Adding the result of parsing to the JViews objects Manager

Once JViews objects have been created and styled from SVG elements, they are added to the JViews object manager. This manager will draw them on a Java view in an optimized way. This is the third and final step when importing an SVG file into JViews.

Some SVG features are very meaningful in an SVG viewer or Internet browser context, but are not applicable to the import context. Among these requirements, some can be adapted to the import context while others should be ignored.

For example, the ILOG JViews import feature ignores declared animations or scripts included in the SVG files. By default, it also ignores metadata or third party namespace elements but let the user customize the mechanism to deal with them.

However, the linking mechanism (<a> element) is managed. For example:

<a xlink:href="http://www.sample.org/myfile.svg">
  <rect x="0" y="0" width="100" height="100" fill="red"/>
</a>

This adds a red rectangle to the JViews manager. When the user clicks on the rectangle, an object interactor is called and tries to load the referenced file in the manager.

However, even elements that are ignored should be memorized so that they can be re-exported later. A user that imports an SVG file into JViews and modifies it (for example by applying a layout algorithm) does not want to lose non-recognized elements (for example a piece of script allowing to interact with the elements) when re-exporting them.

2.4. Batik integration

Considering our choices, the three steps described above can be done in what Batik called a “Bridge”. A Batik “Bridge” is a piece of code that will translate an SVG DOM build by the Batik parser from an SVG file to a structure that fits a graphic toolkit. In Batik this is the GVT but all this code (SVG parser & DOM, CSS parser & DOM, Java 2D extensions, transcoding helpers) could be re-used for another toolkit like JViews just by changing the “Bridge” implementation.

Figure 1: Changing the GVT bridge to a JViews Bridge in Batik

3. Exporting SVG from ILOG JViews

Like any graphic toolkit written in Java, ILOG JViews uses the AWT and Java 2D libraries of the Java platform to draw the graphic objects on the screen. The Java 2D library allows developers writing a toolkit in Java to achieve complex drawing operations. This is done using complex shapes and advanced features such as alpha composition, gradient fill, affine transformation, and advanced text and font support. In order to reproduce these complex drawings in an XML format, the format must cover the advanced features of Java 2D. The SVG format has these features as well as some others. That is why SVG does not introduce any limitations when exporting two-dimensional graphics written in Java 2D. The difficulty resides in the choice of the technique to use to produce SVG documents that reflect the object-oriented structure of the toolkit and that are optimal in terms of size and usability.

Two possible approaches were available to translate drawings from the toolkit in SVG—the Drawing approach and the Object-oriented approach. These approaches were evaluated in order to choose the one most appropriate for ILOG JViews.

3.1. The drawing approach

The drawing approach consists in translating all drawings done with Java 2D into SVG. This technique is implemented by sub-classing thejava.awt.Graphics2D class of the Java 2D library. It is through this class that all the drawings are performed in Java 2D. By sub-classing and implementing all the drawing primitives such that they produce SVG elements instead of drawing directly on the screen, it is possible (in theory) to transform any drawing done in Java into an SVG document.

This technique is very close to what the Java platform does when printing. In order to print in Java 2D, the Java platform substitutes the java.awt.graphics2D instance with an instance suitable to translate the drawing primitives into equivalent printer commands. An example of this technique is given here:

The following Java 2D code (where g is an instance of Graphics2D):

Rectangle rectangle = new Rectangle(10,10,100,100);
//sets the current color to red
g.setPaint(new Color(255, 0, 0)); // sets the line width to 10
g.setStroke(new BasicStroke(10)); // draws the outline of the rectangle
g.draw(rectangle); // sets the color to blue
g.setPaint(new Color(0, 0, 255)); // fills the rectangle
g.fill(rectangle);

produces the following output:

Figure 2: A blue-filled rectangle with a red outline of width 10

If no smart technique is used to reduce the size of the SVG output, the produced SVG document will probably contain two SVG elements. This is because there is one call to the Graphics2D.draw method and one to the Graphics2D.fill method. The resulting SVG elements may look like this:

<rect x="10" y="10" width="100" height="100"
  style="fill:none;stroke:red;stroke-width:10"/>
<rect x="10" y="10" width="100" style="fill:blue" />

With this technique, exporting graphic objects from the toolkit into an SVG document consists of calling the draw method of each graphic object instance with the specialized java.awt.Graphics2D parameter.

3.2. The object oriented approach

The second approach is to take advantage of the object-oriented structure of the toolkit. The toolkit features Java classes such as rectangles, lines, polylines, polygons, text, and images. Instead of reusing the ‘draw’ method of each class, a specific translation method for each graphic object can be created.

Since the translation process is specific for each graphic object, the translation into SVG of a rectangle object will then consist of creating only one SVG <rect> element (since only one SVG element is required to draw a rectangle with SVG).

A rectangle filled with blue surrounded with a red line of thickness 10 will be translated into the following SVG element:

<rect x="10" y="10" width="100" height="100"
  style="fill:blue;stroke:red;stroke-width:10"/>

3.3. Advantages and disadvantages of different approaches

The advantages of the first technique are that it is not limited to a graphics toolkit such as JViews, and can be used for any type of Java tool that uses Java 2D for drawing. Since this technique does not need to know the classes of the toolkit, it allows users of the toolkit that define new classes to take advantage of the SVG generation.

However, this technique leads to several major drawbacks. One such drawback is that it is not easy to handle images using this technique. In SVG, an image will be pointed to by its URL. In Java, images are handled with the java.awt.Imageclass. In many cases there is no URL associated with this image (because the image is created by some Java code) or there is no way to know the URL from which the image was loaded.

In addition to this problem, the resulting SVG document, when using the first approach, is likely to be larger in size and more complex than in the second technique. This is because the first approach does not take advantage of the notion of graphic objects of the toolkit. By taking advantage of this notion, you can produce the SVG elements that best fit the drawings you need. It may become crucial to get the best SVG when you need to associate scripting with the generated SVG document.

A grouping object can be used to illustrate these differences: Most 2D toolkits provide the ability to group graphic objects together using a grouping object. This grouping object does not draw anything itself but provides a way to logically group objects together so that a group of objects can be manipulated as a single object. If the first technique is used without any prior knowledge of the graphic objects, the grouping object will not produce any SVG elements. With the second technique we can produce an SVG grouping element (the <g> element) and thus mimic the object oriented structure of the toolkit and allow further scripting to manipulate objects of the group as a whole.

Another example that illustrates the differences between the two approaches is the definition of objects that have particular behaviors. For example, if an object must always keep the same size in SVG regardless of the zoom level, we must associate a piece of script to this object to let it behaves correctly in SVG. Such behavior cannot be achieved using the first technique, since you need to understand the internal logic of the graphic object.

3.4. Generating SVG in ILOG Jviews

A mix of both approaches has been chosen for the ILOG JViews Component Suite. That is, we take advantage of the notion of graphic objects to produce the most suitable SVG for each predefined graphic object class of the library but if the user has his own graphic objects, he has the ability to directly dump them using the Batik implementation of an SVG generating java.awt.Graphics2Dwithout having to code his own translation method.

Figure 3: SVG Generation in ILOG JViews

3.5. Compression Techniques

When generating SVG documents, the JViews SVG generator uses several techniques to reduce the size of the SVG documents. The size of the resulting SVG document is crucial because a small size will allow a fast download. In addition to the traditional compression through GZIP of the generated SVG file, two main techniques to reduce the size of the SVG document are used in ILOG JViews: the compression of path data, and reusing style.

3.5.1. Compression of path data

The <path> element of SVG allows you to define any type of shape. The shape is defined by the 'd' attribute of the <path>element. The following example specifies a path in the shape of a triangle (The shape is expressed by a set of command letters; the 'M' corresponds to a moveto command, the 'L' indicates a lineto command, and the 'z' a closepath command).

<path d="M 10000 10000 L 10004 10004 L 9996 10004 z"/>

Compression of the 'path' element can take place in the definition of the path data. There are several techniques to compress the size of the path data.

First, all non-necessary spaces can be removed. The data is then expressed as "M10000 10000L10004 10004L9996 10004z". Then, the letter for the command can be removed when it is the same as the previous command letter, which leads to "M10000 10000L10004 10004 9996 10004z". This does not make a big difference since a space must then be added.

The most important point for compression is to use the command letter that will generate the smallest path. The SVG format provides relative versions of each command (upper case means absolute coordinates, lower case means relative coordinates). Therefore, when the coordinates are very large but the bounding area of the shape is small, it is more interesting to use relative coordinates. The following examples display the same triangle:

<path d="M10000 10000L10004 10004L9996 10004z"/>

<path d="M10000 10000l4 4l-8 0z"/>

Another easy way to compress the path data is to use special command letters for the horizontal and vertical lines (H and V command letters). This leads to the following:

<path d="M10000 10000l4 4h-8z"/>

This optimization is interesting in JViews when translating map data with coordinates that can be expressed as 'large' latitudes and longitudes and that displays only a small area of the world. These compression techniques are not possible when using the <polyline> element of SVG because the control points of this element are expressed as a list of absolute points. However, since the 'polyline' element can be easily expressed with a <path> element, another way to compress is to translate polyline objects into SVG <path>elements.

3.5.2. Compression of style

In many two-dimensional displays we may find graphic objects that have the same styling parameters, for example, the same color. In these cases, the style can be reused and placed in the definition section of the SVG document.

For example, the following SVG document containing two rectangles that have the same style:

<svg> 
<defs /> 
<rect x="210" y="10" width="100" height="100"
  style="fill:blue;stroke:red;stroke-width:10"/> 
<rect x="10" y="10" width="100" height="100"
  style="fill:blue;stroke:red;stroke-width:10"/>
</svg>

can be replaced with this one:

<svg> 
<defs> 
  <style type="text/css"/> .C0 {fill:blue;stroke:red;stroke-width:10} </style>
</defs> 
<rect x="210" y="10" width="100" height="100" class="C0"/> 
<rect x="10" y="10" width="100" height="100" class="C0"/>
</svg>

This reduces the size of the resulting SVG file when many objects have the same style. Of course, this operation is optional since re-using the same style may not be appropriate in all cases.

4. Using SVG generation in a thin-client context

The ability to export SVG documents from a two-dimensional framework in Java (such as JViews) is very interesting in a thin-client context. In such an architecture, the JViews library is used on the server side to collect the data of the application and create the appropriate display for the application. This is done, for example, using the Map package to import map data and the Graph Layout package to place network information on top of a map. The SVG generation is then used to publish the graphic to a client.

Figure 4: Thin-Client Application using SVG Generation

So far, such applications have been done by generating raster images for the client (PNG images for example). With SVG, such applications will get the benefit of vector graphics on the client side. This means a better drawing quality, the ability to zoom and pan on the client side without requesting new data from the server, and the ability to interact with individual graphic objects on the client side. However, using SVG on the client side raises some problems and questions for applications that use structured graphics very intensively, such as mapping applications.

Today, most applications that show maps on the web use images generated by a map server. Using SVG to draw maps that contain a lot of information can be difficult because the size of the SVG file may become too big (compared to an image that has a predictable size). That is why for an application that needs to display the vectorial information of a map, a mix of images and SVG will probably be the best solution. The SVG part of the map will then be limited to elements that require interaction with the user on the client side.

Another difficult problem with applications that display maps is that the amount of data at different zoom levels is not usually the same. In fact, the data might be completely different (if your application can zoom from a world map to the street level for example). In this type of application, you cannot take full advantage of the zooming capabilities of SVG on the client side; you have to query the server again when zooming.

The last problem is the notion of layers. This is lacking in SVG. Map data is always organized in terms of 'themes' or 'layers'. A layer contains map data of the same type, for example rivers or towns. This notion gives the ability to hide or show a specific layer easily. Although this notion does not natively exist in SVG, there are means to implement it. Objects of the same layer may be grouped in the same SVG group element 'g', allowing you to turn the visibility of the group on or off. They can also share a common style, which also allows you to turn on or off the visibility of all elements at once. Finally, another solution can be to generate an SVG document for each layer and superpose them in the browser.

Since SVG allows us to manipulate individual graphic objects on the client side, it is natural to think that in applications that display information that varies over time, such as weather information or alarms in a network management system, only the dynamic information would need to be updated and not the static part. This also raises the complex problem of keeping in sync the SVG document and the server side objects without reloading the full SVG.

In conclusion, we see how Batik helps a lot in building an SVG support around a Java 2D toolkit by offering to the developers a set of basic functionalities. When used with additional features available in ILOG JViews such as reduction of SVG file size, access to various data sources or graphic object layout management, SVG format opens many new opportunities for applications with complex needs in dynamically generated vector graphics. And there are still many possibilities to explore.

Bibliography

[SVG 1.0] SVG W3C Proposed Recommendation http://www.w3.org
[CSS 2] CSS 2 W3C Recommendation http://www.w3.org

Biography

Emmanuel Tissandier
Software Project Manager
ILOG, Inc.
France
Email: etissandier@ilog.fr Web: www.ilog.com

Emmanuel Tissandier - Emmanuel Tissandier has been working for 10 years as a software engineer in object oriented environments. He started with the development of CASE tools at Rank Xerox and joined the Visualization R&D team at ILOG in 1995. Since 1997, he has been the R&D Project Manager for the ILOG JViews Component Suite, a product for delivering two-dimensional structured graphics, cartography, diagrams, and Gantt charts in Java.

Christophe Jolif
Software Engineer
ILOG, Inc.
France
Email: cjolif@ilog.fr Web: www.ilog.com

Christophe Jolif - Christophe Jolif is an R&D Software Engineer mainly working on the ILOG JViews Component Suite, the ILOG Java vizualisation framework. He has been working for ILOG since 1997, and is representing the company at the Scalable Vector Graphics (SVG) W3C Working Group. He has implemented the SVG import and export features in ILOG JViews and is now working on the SVG Batik project at Apache.