http://xmlgraphics.apache.org/http://www.apache.org/http://www.w3.org/

Home

Overview
FAQ
Wiki
License
Download
Install
Demo

In the news

Tools and Apps
Browser
Rasterizer
Font Converter
Pretty-printer

Architecture
API (Javadoc)
Generator
DOM API
JSVGCanvas
Transcoder API

Scripting Intro
Scripting Features
Java Scripting
Security

Extensions

Testing

Contributors
Mail Lists

SVN Repository
Bug Database

Status

Glossary


Introduction

What follows is a little introduction to scripting basics, an example of how it could be useful and ways to go a little bit further.


Scripting Basics

As the ECMAScript (JavaScript) language is one of the most popular scripting language and as the SVG specification states that an SVG conforming implementation must support it, the ECMAScript language is supported in Batik through the Mozilla ECMAScript interpreter called Rhino (js.jar ). Even if it is the only scripting language provided with standard with the Batik distribution, other languages such a Python or Tcl can also be supported.

Note:All examples in this section will use ECMAScript.

There are two places in an SVG file where you can put scripts.

The first one is in the <script> element where you can put the definition of your functions or some general code to be executed when the element will be read.


<svg width="100" height="100">
  <script type="text/ecmascript">
    // ECMAScript code to be executed 
  </script>
  <!-- Your SVG elements -->
</svg>

You can also put script in response to user or document events using attributes on SVG elements. As shown in the previous example, the scripting language must be set on the <script> element. However for event handling the default language type "text/ecmascript" is already set. If you want to change it you can use the contentScriptType attribute on the <svg> element.

In most cases, the event attribute will only call a function defined in a <script> section, however as you can see below it can also contains regular code.


<svg width="100" height="100">
  <rect x="0" y="0" width="10" height="10" 
         onclick="evt.target.setAttribute('fill', 'blue')"/>
  <!-- Your SVG elements -->
</svg>

For more information on using scripting in SVG you can have a look at:


How to use Scripting in Batik

The following simplified example that you can find in your Batik distribution displays a simple message in response to user events:

<svg width="450" height="500" viewBox="0 0 450 500">
    <script type="text/ecmascript">

    function showDialog(msg) {
        alert(msg);
    }
    </script>
    <g>
        <circle cx="137.5" cy="110" r="20" style="fill:crimson"
          onmousedown="showDialog('onmousedown')"/>
        <circle cx="312.5" cy="110" r="20" style="fill:crimson"
          onmouseup="showDialog('onmouseup')"/>
    </g>
    <g transform="translate(0 80)">
        <circle cx="137.5" cy="110" r="20" style="fill:crimson"
          onmouseover="showDialog('onmouseover')"/>
        <circle cx="312.5" cy="110" r="20" style="fill:crimson"
          onmouseout="showDialog('onmouseout')"/>
    </g>
    <g transform="translate(0 160)">
        <circle cx="137.5" cy="110" r="20" style="fill:crimson"
          onmousemove="showDialog('onmousemove')"/>
        <circle cx="312.5" cy="110" r="20" style="fill:crimson"
          onclick="showDialog('onclick')"/>
    </g>
</svg>

You can see in the above example that the <script> element contains the definition of a single function: showDialog.

This function will be called thanks to the Batik event handling mechanism in answer to user events. The function is registered to listen to mouse events on the various <circle> elements.


Going Further

Batik as an extensible API provides the ability to customize the scripting module to go beyond the simple support of ECMAScript language in SVG files.

Customize the Rhino interpreter

A useful example of customization of the Rhino interpreter comes from the fact that the ECMAScript specification doesn't provide any I/O predefined facilities to interact with the console . However it is very common for ECMAScript compatible languages to provide a function named print to output messages to the console. We will describe here an example of cutomization of the Batik Rhino interpreter to add such functionality to it.

You should first subclass the default Batik ECMAScript interpreter to add the functionality to it as below.


public class ExtendedRhinoInterpreter extends RhinoIntepreter {
    public ExtendedRhinoInterpreter() {
        super(); // build RhinoInterpreter
        final String[] names = { "print" }
        try {
            getGlobalObject().
	            defineFunctionProperties(names, 
	                          ExtendedRhinoIntepreter.class,
                                  ScriptableObject.DONTENUM);
        } catch (PropertyException e) {
            throw new Error(e.getMessage());
        }
    }
    
    public static void print(Context cx, Scriptable thisObj,
                             Object[] args, Function funObj) {
        for (int i=0; i < args.length; i++) {
            if (i > 0)
                System.out.print(" ");
	    
            // Convert the arbitrary JavaScript value into 
            // a string form.
            String s = Context.toString(args[i]);
	    
            System.out.print(s);
        }
        System.out.println();
    }
}

Now, you should tell to Batik to use this interpreter instead of the default one. For that, you should first define a factory to create instances of your interpreter.


public class ExtendedRhinoInterpreterFactory 
  implements InterpreterFactory {
    public Interpreter createInterpreter() {
        return new ExtendedRhinoInterpreter();
    }
}

Then, you should build an IntepreterPool that will use this factory and set the pool on the BridgeContext of your application.


org.apache.batik.bridge BridgeContext ctx = ...;
org.apache.batik.script.InterpreterPool pool =
    new org.apache.batik.script.InterpreterPool();
pool.putInterpreterFactory("text/ecmascript", 
                           new ExtendedRhinoInterpreterFactory());
ctx.setIntepreterPool(pool);

For example if you are using the Batik SVGBrowser application you should be able to use the previous piece of code on a subclass of the JSVGCanvas class in the createBridgeContext() method.


Have your own interpreter

If you want to use SVG files with your own scripting language in it, you can do it with Batik. You will need to define your own class of Interpreter and register it to the InterpreterPool with the right type for the language as in the example above.




Copyright © 2000-2005 The Apache Software Foundation. All Rights Reserved.