SVuGy - Exploring the Space between Procedural and Declarative Graphics

Keywords: SVG , Ruby (programming language) , Object-Oriented Graphics, Domain-Specific Language (DSL)

Martin J. DÜRST
Aoyama Gakuin University
Fuchinobe 5-10-1
Sagamihara 229-8558
Japan
duerst@it.aoyama.ac.jp

Biography

Martin is an Associate Professor in the Department of Integrated Information Technology, College of Science and Engineering, Aoyama Gakuin University. From 1997 to 2005, Martin was a Team Member of the World Wide Web Consortium, leading the Internationalization Activity, based at Keio University and at MIT. One of the main drivers of internationalization for the Web and the Internet, Martin published the first proposals for domain name internationalization and composite character normalization, and is the main author of the W3C Character Model and the IRI (Internationalized Resource Identifier) specification. Before getting involved in internationalization and the World Wide Web, Martin did research in computer graphics and image processing since the mid 1980es. He has a Dr.sc. in Computers Science from Tokyo University with a thesis on progressive image transmission and compression, and a lic.oec.publ. from the University of Zurich in computer science, management, and Japanese studies. Besides the topics mentioned above, Martin's research interests also include software engineering and programming languages.

Makoto FUJIMORI

Biography

Makoto is a Master Course student in the Intelligence and Information Course of the Graduate School of Science and Engineering of Aoyama Gakuin University. His research interests include computer graphics, animation, and cognitive science.

Takeshi MAEMURA

Biography

Takeshi is currently a bachelor student of Integrated Information Technology in the College of Science and Engineering of Aoyama Gakuin University. His research interests include JavaScript, Ruby and user interfaces.

Tohru KOGA

Biography

Tohru is currently a bachelor student of Integrated Information Technology in the College of Science and Engineering of Aoyama Gakuin University. His research interests include XML and Ruby.

Kazunari ITO

Biography

Kaz received his Ph.D. Degree in Computer Science from Keio University in 2005. He is currently an Assistant Professor in the Department of Integrated Information Technology, College of Science and Engineering, Aoyama Gakuin University. His research interests include semantic web, natural language processing, multimedia information processing, e-learning and application of pictograms.


Abstract


We present a new framework and library, called SVuGy, to create SVG graphics using the object-oriented scripting language Ruby. Using Ruby-specific features, we achieve a high degree of descriptiveness while conserving the possibility to use a full programming language where necessary. In the context of SVuGy, we explore the design space between procedural and declarative graphics and the transition between these two idioms.


Table of Contents


1. Introduction
     1.1 Motivation and Goals
     1.2 Overview
     1.3 Availability
2. Programming and Domain-Specific Languages
     2.1 Declarative versus Procedural
     2.2 Domain-Specific Languages
     2.3 The Ruby Scripting Language
          2.3.1 Ruby Syntax
          2.3.2 Code Blocks
          2.3.3 Metaprogramming
          2.3.4 Other Relevant Ruby Features
3. SVuGy Syntax and Low-level Features
     3.1 Basic Object Construction
     3.2 Parameter Passing
     3.3 Using Variables
     3.4 Styling
     3.5 Transformations
4. Higher-Level Graphics Elements
     4.1 Rotated Text
     4.2 General Facilities for Graphics Objects
     4.3 Repetition and Alignment
5. Related Work
6. Conclusions and Future Work
Bibliography

1. Introduction

We present a new framework and library, SVuGy, for creating and manipulating SVG documents. The framework is written in the programming language Ruby [Ruby]. The name SVuGy is a combination of the consonants from SVG and the (semi)vowels from Ruby, and is pronounced similar to "sveegee", in a sweeping, dynamic way. In the context of this framework, we explore the design space between declarative and procedural graphics.

1.1 Motivation and Goals

The motivations for SVuGy are twofold: Research into programming languages, computer graphics, and Web formats, and the easy and quick generation of graphics for lecture materials.

The first author is using XHTML with the CSS projection mode for all of his lecture slides. With the increasing support of SVG in a wide variety of browsers, it seemed feasible to use SVG for drawings and diagrams in lecture materials. The two main ways to create SVG graphics are to write raw XML by hand with a text editor, and to create graphics interactively using a drawing tool. However, both can be very tedious: Using a text editor involves overhead for typing in and browsing through XML markup, and using an interactive drawing tool can limit editing efforts because the final result is easily visible but underlying structures such as groupings, constraints, and meta-information are hidden and therefore easily neglected (see [Beyond]).

So for our purposes, we looked for something that as much as possible combined the advantages of both approaches while avoiding their disadvantages. We of course do not claim that everybody is best served with a text-based system for creating graphics, but we wanted to try and find out how far we could get with a text-based system. Ideally, such a text-based system should be highly descriptive, intuitive, and concise while offering the full flexibility of a programming language. Creating a new programming language would have been an option, but it would have needed a lot of implementation effort. Using the programming language Ruby turned out to make it possible to create a system that was usable very quickly, concise and highly descriptive, easily evolvable, and increasingly powerful.

1.2 Overview

This paper describes the state of our research and of our system after only a few months of implementation and use. Chapter 2 discusses the contrast between programming and domain-specific languages and explains the features of the programming language Ruby that make it extremely well suited for our task. Chapter 3 describes the syntax and the low-level features of our system. Higher-level features, as far as they are available currently, are discussed in Chapter 4. This is followed by a comparison with similar systems, conclusions, and a discussion of future work.

1.3 Availability

For additional up-to-date information on SVuGy, please see [SVuGyHome]. A first public version of SVuGy is made available as a Ruby Gem (the Ruby-specific package format) at [SVuGyGem] in time for the SVG Open 2007 conference.

2. Programming and Domain-Specific Languages

2.1 Declarative versus Procedural

Declarative formats are preferable because they are easier to understand and to manipulate, and are inherently more secure. On the other side, generating data from programs offers more power and flexibility. Formats on and for the World Wide Web are continuously evolving from procedural scripts towards descriptive data formats. However, this development takes time, first because identifying the necessary features for a descriptive language is difficult, second because it takes time to agree on details including syntax, and third because deploying a declarative format means implementing and deploying new versions of user agents to the whole user population.

2.2 Domain-Specific Languages

Declarative formats are by nature domain-specific, and are also called Domain-Specific Languages (DSLs [DSL]). In general, DSLs are external, i.e. they are independent of a programming language. However, DSLs can also be internal, i.e. be part of a programming language. Due to the syntax and semantic restrictions of most programming languages, an internal DSL usually does not look much different from an API, i.e. a collection of data types, functions and methods for a specific purpose, with a significant syntactic overhead. However, the scripting language Ruby makes it very easy to create internal DSLs, where a syntax that looks and feels very declarative is part of a program in a way that always allows access to the full programming language.

2.3 The Ruby Scripting Language

Ruby is a pure object-oriented, interpreted programming language created in Japan. It started as a 'better Perl', but also includes ideas from Smalltalk, Lisp, and several other programming languages. It has gained much popularity recently, in part due to Ruby on Rails [Rails], a Web application framework based on convention over configuration. There are three main features that make Ruby extremely well suited for creating internal DSLs: Concise syntax, the use of code blocks, and metaprogramming.

2.3.1 Ruby Syntax

Ruby syntax includes various features that make it very well suited for creating domain-specific languages. On first approximation, Ruby syntax is close to C, C++, or Java (as opposed to e.g. Lisp or PostScript), in particular on the operator or expression level. However, one of the goals of the creator of Ruby, Yukihiro Matsumoto, was to avoid any unnecessary syntax, even at the expense of making parsing more complex. Observing that most lines in a program contain exactly one statement ending in a semicolon, Ruby allows trailing semicolons to be dropped. The cost for this is that line breaks in the middle of a statement or expression are restricted to points after operators. Also, parentheses around function and method parameters can be dropped whenever the result can be interpreted unambiguously. Dropping semicolons and function parentheses alone provides for much of an open and concise look of a DSL.

2.3.2 Code Blocks

Code blocks in Ruby are pieces of code enclosed between do and end or between { and }, the two alternatives having slightly different priorities. Code blocks can also take parameters. Each method can take a code block, and can call it as many times as necessary, with different parameters. Ruby itself uses code blocks extensively for iterators. For a DSL, code blocks mainly provide the facility to group a number of statements and use them in a certain context.

2.3.3 Metaprogramming

Metaprogramming refers to the facility to create new program functionality while the program itself is running. Ruby comes with a strong set of metaprogramming features, both on a symbolic level as well as by simply evaluating a character string as a piece of code. The background for this is that in Ruby, all programming code, even the creation of new classes and the definition of methods, is done as part of program execution rather than as a separate step. Also, by default all classes and objects in Ruby are open, i.e. new methods or fields can be added at any time. Ruby's metaprogramming features are supported by a collection of reflexive methods, allowing to examine the current program structure. Metaprogramming is used in a DSL to create new procedural functionality in a declarative way.

2.3.4 Other Relevant Ruby Features

Besides the features mentioned above, Ruby's complete object-orientedness fits together extremely well with graphic drawings. It is not by accident that basic shapes such as rectangles and circles, and operations on these basic shapes, are often used as examples when introducing object-oriented programming. Ruby's strong concern for concise code and high programmer productivity also was and is of great benefit for our project.

3. SVuGy Syntax and Low-level Features

For ease of use and understanding of a domain-specific language, a compact and intuitive syntax is crucial. This section describes the main features of the SVuGy syntax, and how they relate to SVG and Ruby syntax. However, this section is not intended as a manual for SVuGy syntax, as details of SVuGy syntax are still under development.

3.1 Basic Object Construction

The core concept of SVuGy is a very simple and intuitive way of creating SVG graphics objects. Example 1 shows how to express a group containing a rectangle and a circle in SVuGy. The syntax can be understood completely declaratively: There is a group (<g> in SVG) that contains a rectangle (<rect>) and a circle (<circle>). The rectangle is placed at x='50' and y='50' and is 150 units wide and 100 units high, and the circle is centered at x='250' and y='150' with a radius of 75 units.

g {
  rect 50, 50, 150, 100
  circle 250, 150, 75
}

Example 1: A group with a rectangle and a circle

Despite being completely declarative, the syntax in Example 1 is actual Ruby code. When executed, it constructs the group with the rectangle and the circle. We explain the details of how this happens here, although these details are not needed for the understanding of the remainder of the paper. The method rect is a so-called factory method, which creates a new object, in this case a rectangle. The parameters to the rect method are passed to the actual rectangle object constructor (i.e. the method Rect.new). Also, a parent-child relationship is established between the new rectangle and the object to which the rect method is sent. This object happens to be the group produced by the g method at the start of our example, because the g method executes the block (the code between { and }) that it receives in its own context. This is done by using the Ruby method instance_eval.

The syntax in Example 1 is nothing more than SVG rewritten with different punctuation. To a large extent, this is an issue of taste, but to the extent that there are less characters to type, and less characters to look at when reading the code, this can help quite a bit. For interoperability, it is very difficult to understate the benefits of a generic format such as XML, but for direct user interaction, a more specific format may be more appropriate. XQuery and RelaxNG are two recent examples where both an XML-based and a more specific format have been standardized. In our case, we are not at all interested in standardizing SVuGy or using it over the Web, but in efficient description of drawings by the user.

Obviously, to start creating an SVG drawing, we need some overall context. This is provided by creating an SVuGyDocument object with SVuGyDocument.new. The block passed to the new method then contains the factory methods corresponding to the top-level elements in the document.

Once created, a SVuGyDocument object can be serialized to SVG with the to_svg method, and this serialization can be output as desired. A very small full example, in the syntax used at the time of writing this paper, and without any styling information, is shown in Example 2. Of course, the overhead of creating the full document can be further reduced, and is much smaller in examples that are larger than Example 2.

require 'SVuGy'

drawing = SVuGyDocument.new(800, 400) do
  g {
    rect 50, 50, 150, 100
    circle 250, 150, 75
  }
  text 'Hello SVuGy!', 50, 40
end

print drawing.to_svg

Example 2: Full SVuGy example

3.2 Parameter Passing

For the construction of graphics objects, we basically use positional parameters. This is the main way to identify parameters is most programming languages, including Ruby. XML attributes, and therefore SVG 'parameters', are of course named. This creates a slight gap between SVG and SVuGy: a SVuGy user has to learn the order of the parameters. However, this is not problem at all, because SVG documentation consistently introduces the main attributes in the same order. As an example, the order is consistently x, y, width, height for a rectangle.

Positional parameter passing is very concise for the core parameters of a graphics object, but does not scale to the large number of parameters/attributes potentially needed. One way get around this limitation is to use methods on the constructed object rather than parameters. This is done in particular for style properties/attributes and for transformations, and will be described in detail in Section 3.4 and Section 3.5.

In many cases, we also make some parameters optional. Currently, in general the position-related parameters are optional whereas the size-related parameters are mandatory. For the rectangle, this means that x and y (as a group) are optional, but width and height are mandatory. The reasoning behind this is that we expect that on average, automatic placement will be more frequent than automatic sizing.

Variables in Ruby, including method parameters, do not have a type. This means that objects of any class can be passed to a method. We use this to increase the flexibility of parameter passing by distinguishing parameters based on their type. A typical example is to set an identifier for a graphics object. The class corresponding to an id in Ruby is Symbol, similar to Lisp atoms. Symbols are written with a leading colon. A factory method for a graphics object can easily check whether the first parameter is a Symbol, and if it is, use this symbol for the id of the graphics object. The rest of the parameters are then processed as usual. We call this type of parameter passing typed parameter passing. Typed parameter passing is also used to replace two numeric parameters forming a coordinate pair with a single Point object. Using typed parameter passing, the above rectangle may be written as follows:

rect :myID, point1, 150, 100

Here, the rectangle is given the id myID and x and y values from point1, a point defined earlier.

Ruby itself does not allow optional parameters to come before required parameters, nor does it allow to automatically assign parameters based on class. We therefore only use the lowest level parameter passing functionality in Ruby, the ability to pass a list of parameters as a variable-length array. Analysis and processing of parameters is then done 'by hand'. This was originally done using various control statements (if/while/...), but this quickly proved to be very difficult to maintain and extend. We therefore switched to a more descriptive approach, parsing the list of attributes using a specially designed grammar. We plan to report on the details of this approach elsewhere.

3.3 Using Variables

Variables are another well-known and widely used feature of programming languages. In SVuGy, their main use is to create a reference to a graphics object:

r1 = rect 50, 50, 150, 100

This reference can later be used e.g. to find the bottom-right corner of the rectangle:

line r1.br, 400, 400

One main limitation that the SVuGy user encounters is that in Ruby, variables are block-local. This means that a variable first appearing in a block cannot be referenced outside this block. The code in Example 3 will produce an error because the variable r1 is undefined outside the block passed to the g factory method.

g {
  r1 = rect 50, 50, 150, 100
  circle 250, 150, 75
}
line r1.br, 400, 400

Example 3: Block scope of variables

There are three ways to get around this problem, two provided by Ruby and one provided by SVuGy. The first way is to declare the variable once before the block. In Ruby, there is no way to just declare a variable, but assigning some (arbitrary) value to a variable declares it as a side effect. In Example 3, we could add r1 = 'arbitrary' before g. The second way uses global variables. Global variables in Ruby are identified by a $ prefix. In Example 3, we would replace r1 by $r1. Neither predeclaration nor using global variables is very natural.

The third way is to use an SVG id. We already have described how graphics objects can be given ids in Section 3.2. Instead of r1 = rect 50, 50, 150, 100, we write rect :r1, 50, 50, 150, 100. To make sure that we can use r1 in the last line of Example 3, we register the id with the SVuGy document, which allows to check for duplicate ids. We then use Ruby metaprogramming to 'simulate' the existence of a variable named r1. The only potential disadvantage of this method is that an id attribute is added to the rect element in the SVG output even if the id is only used internally in SVuGy.

3.4 Styling

SVG has two ways of indicating style information: a single style attribute using CSS notation internally, and a set of attributes corresponding to style properties. In SVuGy, there are likewise several ways to specify style information, under the assumption that SVuGy users may have different preferences. One distinction parallels the one in SVG: There are both a style factory method as well as methods corresponding to CSS properties. However, we do not use this distinction to decide which way to output style attributes in SVG. The main purpose of providing a style factory method is for style reuse. While style reuse is currently done on the SVuGy level only, we are looking into ways of expressing this style reuse with the class attribute and CSS classes in SVG.

We also use numerous syntactic features of Ruby to provide easy and natural notations for property values. Our treatment of property values is currently string-based, i.e. property values are treated as strings, without any internal analysis. This means that in the general case, property values have to be enclosed in quotes. To relieve the user from the burden of using quotes, we also accept symbols where possible, meaning that the user only has to type a leading semicolon. Also, we use the metaprogramming features of Ruby to add a large number of property value keywords as if they were methods or variable names. As a result, the user can replace fill :black with fill black. For numeric color constants, in CSS denoted with a sharp sign, we are experimenting with using an upper-case H instead of the sharp sign. This would mean that the user simply can write H0066ff instead of #0066ff. Because the sharp sign introduces a Ruby comment, this is the best we can do to align SVuGy syntax with SVG syntax.

For the style factory method, we also currently make some efforts to distinguish two different usage patters: chained and blocked usage. Chained usage denotes the case where the style method is used chained to an object or another method:

what = circle(0, 0, 100).style(fill => black)

Blocked usage denotes freestanding use inside a block:

{
  what = style(fill => black)
}

The reason for distinguishing these two usage patterns is that there are different expectations for the result of the expression (assigned to the variable what in our examples). When chained, the user will most probably understand the style method in an attributive way, expecting the overall result to be the object created by the first factory method (circle in the example). However, when blocked, the natural expectation is that the result is a style object. The distinction between chaining and blocking is currently implemented 'by hand'; we hope that in the future, Ruby will provide some built-in support for this distinction.

The examples above also show an additional feature of the style factory method, namely the ability to use the Ruby hash constant syntax (key => value).

3.5 Transformations

In SVG, geometric transformations get packed into the transform attribute. In SVuGy, there is a separate factory method for each different transform. These methods can be used both chained and blocked.

Making transforms available as objects is important for correctly calculating the relative position of points and other geometric objects. This is shown in Example 4: The starting point of the line is the top right corner of the rectangle. A simple calculation would put that point at 0, 50, but this is only correct in the translated and rotated coordinate system of the group. To create the line as expected, the coordinates of the point represented by rect1.tr have to be converted back to the coordinate system of the parent object of the line.

g {
  translate 20, 50
  rotate 30
  rect :rect1, 0, 0, 50, 50
}
line rect1.tr, 100, 100

Example 4: Relative position of points

4. Higher-Level Graphics Elements

The real benefit of an internal DSL appears when defining higher-level features.

4.1 Rotated Text

This subsection describes a very simple example of abstracting higher-level graphics elements. When developing higher-level graphics elements, we as much as possible are following a need-based approach. This means that we do not try to predict in advance what higher-level graphics elements may be needed, but add them to SVuGy if and when we find a need for them.

A very simple and typical example of this is rotated text. A SVuGy text factory method takes a string and an x, y coordinate pair. Rotating such a text is easily done using a rotate transform. The code for this looks as follows:

text('sample text', 150, 250).rotate -90, 150, 250

After coding a few such texts, we realized that the starting point for the text is virtually always identical to the center of the rotation. To be able to change the text placement more easily, we rewrote this as:

text('sample text', p1=pt(150, 250)).rotate -90, p1

Here, we generate a point on the fly, save it as p1, and then reuse it. If we want to move the text, we only have to change one pair of coordinates. However, this is still clumsy. By introducing a new class of graphic objects, the code becomes much simpler and straightforward:

rotated_text 'sample text', 150, 250, -90

The implementation of rotated_text is very short. We create a class RotatedText,with only one method, the constructor (initialize in Ruby).

4.2 General Facilities for Graphics Objects

Rotated text is only one example of a type of graphics objects that is growing steadily and currently includes arrows, bent lines and bent arrows, regular polygons, speech bubbles, circles with labels, and so on. Each of these can be implemented in the same way as the basic shapes provided by SVG: Create a factory method, and create a class for representing the objects, with the necessary methods. The two main methods that we need are a constructor (called initialize in the case of Ruby) and a method converting the object to SVG (called to_svg).

However, our goal is to make the creation of new graphics object types as simple and easy as possible. Not only does this benefit a SVuGy user who creates her own new graphics object type, but it also shortens and simplifies the code for the basic graphic objects.

To achieve this goal, we use classic object-oriented techniques and patterns as well as metaprogramming. With metaprogramming, we automatically create a factory method for each class that is a subclass of the general Shape class.

Up to now, we have observed that user objects are either variations of basic objects or groupings of basic objects. As an example, an arrow is a line with an arrowhead marker. A circle with a label is a group of a circle and a text label. These identities are established by inheritance (e.g. the Arrow class inheriting from the Line class) and by adding the necessary additional information (e.g. group members) during construction. As a result, the method that creates the actual SVG code can simply be inherited in most cases.

Currently, there are two additional aspects of graphics objects that we are working on, namely attachment points and bounding box. Attachment points serve e.g. to attach lines and arrows to a graphics object. For a rectangle and similar objects, we use the CSS-based terminologies top/middle/bottom and left/center/right, leading to nine attachment points (tl, tc, tr, ml, mc, mr, bl, bc, br). The bounding box is used for the automatic calculation of overall drawing size as well as for alignment operations (see Section 4.3). We currently use a collection of points on an approximate convex hull instead of a rectangular bounding box to get better results for transformed objects. Both of the above aspects are currently mostly implemented 'by hand'.

4.3 Repetition and Alignment

Declarativity is not only important for more complex graphics objects, but also for layout schemes such as repetition and alignment. For both repetition and alignment, we have discovered two different patterns so far, which we call internal and external. An internal repetition includes the object(s) to be repeated, whereas an external repetition references an object declared or defined elsewhere. The distinction can be applied to alignment, too, indeed it is more important for alignment because alignment in two different dimensions may force the use of external alignment.

5. Related Work

In this section, we first look at other libraries that combine Ruby and SVG, and then at other approaches to descriptive graphics.

There are several other libraries using Ruby to produce SVG. All of them use syntax that is considerably more verbose and less flexible than ours. We attribute this to the fact that their main aim is to serve as APIs, i.e. to be used by programmers, rather than (text-oriented) end users.

Ruby/SVG [RubySVG] is a small, clean library for producing simple SVG. Example 5 shows a code example, adapted from some of the examples included in the Ruby/SVG distribution. The lack of factory methods both for graphical shapes as well as for other things such as styles and style properties makes this syntax much more repetitive and less intuitive. There does not seem to be any further development effort on Ruby/SVG since early 2003.

svg = SVG.new('4in', '4in', '0 0 400 400')
svg << SVG::Rect.new(20, 20, 160, 160) {
  self.style = SVG::Style.new
  self.style.fill = 'blue'
}
svg << SVG::Circle.new(100, 300, 80)
print svg.to_s

Example 5: Ruby/SVG code

RVG [RVG] is the SVG-inspired vector graphics part of RMagick. RMagick is the Ruby binding for the widely used and very similar ImageMagickTM and GraphicsMagick image manipulation libraries. As a consequence, RVG is very well suited for creating raster images. Because it comes with its own rasterization engine, it also has no problems converting between absolute and relative units and doing exact calculations for text placement. Example 6 shows an example of RVG syntax, adapted from the RVG tutorial. RVG is more verbose because it explicitly passes the parent object into the block (|canvas| and |body| in the example).

rvg = RVG.new(2.5.in, 2.5.in).viewbox(0,0,250,250) { |canvas|
    canvas.background_fill = 'white'
    canvas.g.translate(100, 150).rotate(-30) { |body|
        body.styles(:fill=>'yellow', :stroke=>'black', :stroke_width=>2)
        body.ellipse(50, 30)
        body.rect(45, 20, -20, -10).skewX(-35)
    }
}
rvg.draw.write('example.gif')

Example 6: RVG code

Rcairo [rcairo] is a Ruby binding for cairo, which can output SVG. However, the structure of the cairo API and therefore rcairo is much closer to that of a traditional graphics pipeline API and therefore much more procedural than Ruby/SVG, RVG, and of course SVuGy.

APIs for SVG in programming languages other than Ruby are likewise bound to be more verbose and less declarative because they cannot take advantage of Ruby's unique features. An example that may come close is the Scheme-based graph library extension described in [LAML].

Programming languages specialized for 2D graphics, such as PenDraw [pendraw], may come close or even slightly surpass SVuGy in terms of usability and descriptiveness, but they are severely limited by the fact that they are not general-purpose programming languages.

We do not include a performance analysis here because our main goal is convenience for the user, not execution speed. If we ever should meet some performance bottleneck, Ruby comes with a built-in profiler, and if necessary, some pieces of SVuGy could be rewritten as a C extension.

6. Conclusions and Future Work

We have tried to show how SVuGy, based on the scripting language Ruby, can integrate declarative and procedural approaches to graphics in a flexible way. This reduces the gap between procedural experimentation and declarative syntax, and supports a fast transition driven by the user's needs. Development happens in fast cycles on two levels: Recurring combinations of graphic objects and layouts are identified, programmed, and made available in a declarative syntax. Recurring programming patterns are identified and abstracted using metaprogramming.

We feel that the synergy between SVG and Ruby and between declarative and procedural graphics exposed by SVuGy is only a start. There is a wide range of topics that we plan to explore in future work. This includes more automatic layout, i.e. by connecting to a library such as graphviz [graphviz], integration with data sources, client-side scripts (e.g. for dynamic layout constraints), high-level support for animation, and simulation of 3D objects. We also plan to address some more practical issues such as better placement of text (difficult because exact measures are not really available), built-in validation support, and fine control over the SVG output (e.g. SVG versions, indenting, output of style information).

Bibliography

[DSL]
Martin Fowler, Domain Specific Language, available at http://www.martinfowler.com/bliki/DomainSpecificLanguage.html
[Beyond]
Robert Schleich and Martin J. Dürst, Beyond WYSIWYG: Display of Hidden Information in Graphics Editors, Computer Graphics Forum, Vol. 13, No. 3, Proceedings of Eurographics '94, pp. C185-194, 1994.
[graphviz]
Emden R. Gansner and Stephen C. North, An Open Graph Visualization System and its Applications to Software Engineering, Software - Practice and Experience, Vol. 30, No. 11, pp. 1203-1233, 2000.
[LAML]
Kurt Nørmark, A Graph Library Extension of SVG, available at http://www.cs.auc.dk/~normark/laml/papers/graph-library-extension-of-svg.pdf.
[pendraw]
Andrew Main, PenDraw - A Language for Improving Take-Up of SVG, SVG Open 2007, available at http://www.svgopen.org/2005/papers/PendrawServerSideSvg/.
[Rails]
Dave Thomas, David Heinemeier Hansson et al., Agile Web Development with Rails, Second Edition,The Pragmatic Programmers, 2006.
[rcairo]
Ruby bindings for cairo, available at http://raa.ruby-lang.org/project/rcairo/.
[Ruby]
Dave Thomas, with Chad Fowler and Andy Hunt, Programming Ruby, Second Edition, The Pragmatic Programmers, 2004.
[RubySVG]
Yuya Kato, Ruby/SVG, available at http://ruby-svg.sourceforge.jp/.
[RVG]
Timothy P. Hunter, Drawing with RVG - A tutorial, available at http://redux.imagemagick.org/RMagick/doc/rvgtut.html.
[SVuGyGem]
Martin J. Dürst et al., SVuGy RubyGem Library, available at http://svugy.rubyforge.org/.
[SVuGyHome]
Martin J. Dürst et al., SVuGy - A Ruby Library for SVG, available at http://sw.it.aoyama.ac.jp/SVuGy/.

XHTML rendition made possible by SchemaSoft's Document Interpreter™ technology.