SVG support in ILOG JViews Component Suite
Emmanuel Tissandier
Christophe Jolif
Find


Abstract
As part of the SVG Working Group, ILOG is implementing 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 helps you do this. We will also see how SVG can be generated 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.

Keywords

Contents
  1. Introduction
    1. What is the ILOG JViews Component Suite?
    2. What is SVG?
  2. Part 1: Exporting SVG from ILOG JViews
    1. The Drawing approach
    2. The Object-oriented approach
    3. Advantages and disadvantages of the different approaches
    4. Generating SVG in ILOG JViews
    5. Compression techniques
      1. Compression of path data
      2. Reusing styles
  3. Part 2: Importing SVG into ILOG JViews
    1. Creating JViews graphic objects from SVG Elements
      1. Parsing an SVG file as an XML file
      2. Mapping the parsed elements
        1. Simple SVG graphic elements
        2. The <text> element
        3. The <path> element
    2. Applying a style to imported graphic elements
      1. Parsing styles described with a CSS syntax
      2. Applying the styles to the JViews Object using Java 2D
        1. Extension of the JViews Toolkit
        2. Extension of Java 2D
    3. Adding the results of parsing to the JViews Object Manager
  4. Part 3: Using JViews SVG generation in a thin-client context
  5. Bibliography

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. Since last year, ILOG has been a member of the SVG Working Group in the W3C and has started implementing SVG in the ILOG JViews Component Suite.
What is the ILOG JViews Component Suite?
The ILOG JViews Component Suite is composed of several packages addressing different types of application problems:
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.
Implementing SVG in JViews consists of:
This paper is divided into the following parts:
Previous Previous Table of Contents
Part 1: 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 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.
Part 1 of this paper is divided as follows:
The Drawing approach
The Drawing approach consists of translating all drawings done with Java 2D into SVG. This technique consists of sub-classing the java.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 1 . 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 Graphics.draw method and one to the Graphics.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.0" />
<rect x="10" y="10" width="100" height="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.Graphics parameter.
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.0" />
Advantages and disadvantages of the 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 possible 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.Image class. 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 the problem of images, 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 do not zoom. If an object must always keep the same size in SVG regardless of the zoom level, its coordinates may be expressed in pixels. This tells the SVG viewer not to zoom the object. Such behavior cannot be achieved using the first technique, since you need to understand the internal logic of the graphic object.
Generating SVG in ILOG JViews
The second approach 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 graphic object class.
Exporting a JViews drawing in SVG is implemented as a type of output stream called the SVGOutputStream. To create an SVG document from the toolkit the user simply creates an SVGOutputStream and writes the contents of the manager (the JViews data structure that contains the graphic objects) to this stream.
Compression techniques
When generating SVG documents, the JViews SVGOutputStream 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. Two techniques to reduce the size of the SVG document will be discussed:
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 (taken from [SVG 1.0]) 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, the L’s indicate a lineto, and the z a closepath).
<path d="M 100 100 L 140 100 L 120 140 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 “M100 100L140 100L120 140z”. Then, the letter for the command can be removed when it is the same as the previous command letter, which leads to “M100 100L140 100 120 140z”. 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 JViews polyline objects into SVG ‘path’ elements.
Reusing styles
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:2" />
<rect x="10" y="10" width="100" height="100"
style="fill:blue;stroke:red;stroke-width:2" />
</svg>
can be replaced with this one:
<svg>
<defs>
<style>
<![CDATA[
.C0 {fill:blue;stroke:red;stroke-width:2.0}
]]>
</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.
Previous Previous Table of Contents
Part 2: Importing SVG into ILOG JViews
Other than the ability to export SVG files from JViews, it may also be interesting to have an import feature. There are two main reasons for adding this import feature to JViews. The first reason is interoperability. With SVG import added to the export facility, JViews will be able to read documents built with other software and possibly modify them for external use. The second reason is that this feature will allow end users to develop SVG-enabled applications with the library. This means that their web or desktop applications will display and edit SVG documents without coding effort.
Importing an SVG file into JViews is done in three steps. These steps are described in this part as follows:
The first two steps are distinct because SVG separates styles from shapes. Style is expressed with the CSS syntax while graphic elements are described using an XML grammar.
Creating JViews graphic 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.
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. 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 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.
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="ref" 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. That is why this solution has been chosen as the import feature for ILOG JViews.
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. The following elements are discussed:
Simple SVG graphic elements
For most SVG graphic elements the translation is very simple.
For example:
<rect x="0" y="0" width="64" height="48"/>
can be translated to the following in Java:
IlvGraphic object = new IlvRectangle(new IlvRect(0, 0, 64, 48));
For example:
<polyline points="0 0 64 48 100 100"/>
can be translated to the following in Java:
IlvPoint[] array = new IlvPoint[3];
array[0] = new IlvPoint(0, 0);
array[1] = new IlvPoint(64, 48);
array[2] = new IlvPoint(100, 100);
IlvGraphic object = new IlvPolyline(array);
For example:
<circle cx="0" cy="0" r="10"/>
can be translated to the following in Java:
IlvGraphic object = new IlvEllipse(new IlvPoint(0, 0), 10);
For example:
<image x="0" y="0" width="64" height="48" xlink:href="image.png"/>
can be translated to the following in Java:
IlvGraphic object = new IlvIcon("image.png", new IlvRect(0,0, 64, 48));
The <text> element
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 100L200 200l10 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. The equations are available in Appendix F of [SVG 1.0].
Applying a style to imported graphic 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. Style is 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.
Parsing styles 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. However, although reliable SAX implementations are available (Sun, IBM), SAC implementations are not currently widespread.
That is why ILOG JViews has first implemented its own limited CSS parser to parse CSS syntax in SVG files. This parser currently implements a limited set of CSS selectors (selectors allow you to associate a style with an XML element): the universal selector, the type selector, the ID selector, the simple class selector, as well as the adjacent, child, and descendant selectors. Not supported are the attribute selector, the pseudo class selector, the import rules, and @ rules in general. Consequently, there is no way to include an external style sheet in the current implementation.
Once read, CSS rule selectors must be compared to SVG graphic 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].
Applying the styles to the JViews Object using Java 2D
Once the style of a graphic element has been computed using the cascade, 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 = new float[2];
float[0] = 2; float[1] = 4;
Stroke stroke =
new BasicStroke(4,
BasicStroke.CAP_ROUND,
BasicStroke.JOIN_MITER,
8, dasharray, 0);
Then the previous pure Java 2D objects are applied to the JViews IlvGeneralPath object:
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. Both these cases will now be described.
Extension of the JViews Toolkit
Some styling properties require 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 not in the JViews toolkit. In this case, it can be implemented by adding a setClip method on JViews graphic objects.
Extension of Java 2D
However, some other possibilities such as the radial color gradients, the multiple color linear gradients, or the image filters are not present in Java 2D and thus cannot simply be added to the JViews objects.
Both gradients have been implemented using the Java 2D java.awt.Paint interface and return a raster filled with the correct color gradient.
Some SVG image filters can be achieved by implementing the Java 2D java.image.RasterOp interface. However, the Java 2D filtering mechanism has some limitations. For example, this mechanism does not support multiple sources. In conclusion, it is better to use the Java Advanced Imaging API, which is an extension of the Java Platform and has more filtering capabilities.
Adding the results of parsing to the JViews Object 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 our 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. It also ignores metadata or third party namespace elements.
However, the linking mechanism can be dealt with through the <a> element. For example:
<a xlink:href="http://www.sample.org/myfile.svg">
<rect x="0" y="0" width="100" height="100"
style="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.
Previous Previous Table of Contents
Part 3: Using JViews 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 2 . Thin-client application using SVG generation
So far, such applications have been done by generating raster images for the client (JPEG 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 that the SVG format opens many new opportunities for applications with complex needs in vector graphics. There are still many possibilities to explore.
Previous Previous Table of Contents
Bibliography
[SVG 1.0] SVG W3C draft Recommendation http://www.w3.org
[CSS 2] CSS 2 W3C Recommendation http://www.w3.org
Previous Previous Table of Contents