Chapter 4. SVG- Code Generation

Table of Contents


Code generation fragments dedicated to SVG (Scalable Vector Graphics).

As usual the same namespace is used for a different code generation.

To-Do : -state is ambiguous and need to be handled within SVG in another way, possible »display« or »visibility«.

There are no coords for groups.

The can2svg arc code is wrong for Zinc –deployed by SvgDumper.

Problems with contextual css.

Auto-screen-shot, for tile based windows. There is nothing for this function either in TkPath or Tk. Only img and pixane provide the needed functionality. Done and tested under AQUA with Tk 8.4 and Img 1.3, results are very bad, hopefully it will work better with new Img versions. Screen-shots are a poor man's solution anyway!

See also: svgcode.tcl, svgdom.tcl, can2svg.tcl, vgcode.tcl, tcldumper.tcl, gstripes.tcl, tcledit.tcl and tcltest.tcl


The code generation is in general split between vgcode (parse) and dumper (compose).

For SVG a different approach is required. The generated SVG is a DOM tree maintained by tDOM.

There is a second part for SVG generation; »dumper« is also used to generate a canvas graphics from a SVG-DOM. That is, the generated DOM is used two-way.

For Zinc: Zinc is included in the SVG generation process, but no zinc-graphics will be generated from the DOM. The second part is only possible for TkPath.

can2svg and svg2can, from Mats Bengtsson As much code as possible is reused from can2svg. This is especially true for the conversion part –but might be eliminated for reaching resolution independence.

svg2can: The second part is most likely handled by the first generation step (two-way). Possibly svg2can could be deployed directly as a counter-test case?

Implemented by tkpdumper.tcl and tkpcode.tcl. In the future zinc might as-well be covered by the SVG Import functionality.

The scope of svg2can.tcl and tkpdumper.tcl is quite different. tkpdumper.tcl deals with both TkPath 0.2 and 0.3 exclusively. svg2can predates TkPath! The conversions target Tk Canvas elements and only partially TkPath 0.2. LinearGradients and RadialGradients, generated by svg2can, cannot be used with TkPath 0.3. svg2can would make a nice starting point for a SVG to Tk Canvas Importer, say: tkcDumper.

There are two ways to generate a DOM in tDOM, from Tcl. First, the DOM is accessed and navigated as-is. Second, an intermediate step is used where nested lists are the intermediates.

The second mechanism is well suited for dumper and well handled by »seteach« anyway ;-).

–It might however require some extensions to seteach, will see to it–

Mats Bengtsson uses nested lists for can2svg, so going that way may help to realize synergies.

The nested lists are then put into the DOM–verbatim.

SVG Definitions:

➊. A Group <g> ... </g> Represents a Window or a group ( identified by a number /tag ) group IDs are either the window name / pathName or 1st tag or ID. In case of ID a generic name is used id=".mywindow"

The representation of a window as a svg group requires an rectangle (as background) and clipping.

Group as of TkPath requires TkPath 0.3 or higher. There is no group element before that.

See also : viewport and mask.

It is desirable to use viewports for each window, then clipping is implied within the viewport. Negative effect is that there is no direct way back from the SVG into a TkPath window. Must think about this issue-

Creation of graphical representations can be done using an intermediate mechanism in which an –alien– graphical representation is created for a window hierarchy. These representation is filtered; duplications, stemming from the hierarchy, and not needed, are eliminated.

These allows for a preview, but as a result no interaction can be preserved for this elements. Because the elements loose to much information to preserve interactions.

groups are difficult to translate, there is a child to parent relationship: the parent group is an attribute of the child and must be transformed into a hierarchical dependency. Done by a cross-table for each window. The DOM tree is directly created whenever a group is encountered.

The same applies for windows, mapped onto groups –uses clipping.

➋. Gradients There are two types of gradients: linear and radial. Both types are used in the general fashion. They do contain <stop /> elements.

Note 03/09/2009 - 13:47 :There is an error inside the TkPath gradient implementation. SVG applies the fill-opacity on gradients as-well. This is ignored inside TkPath. Filter this out in the meantime.

A gradient is defined inside the definition section.

Linear Gradient dimension and orientation: x1, x2, y1, y2

Radial Gradients: <radialGradient> ... </radialGradient>

Radial Gradient dimensions and orientation: cx, cy, r, fx, fy

Gradients other attributes:

spreadMethod="pad" ...

Gradients may inherit attributes from referenced gradients using:


Not used,yet.

Gradients require TkPath 0.2.4 or higher or TkPath 0.3 or higher –depends on the translation TkPath 0.2 knows global gradients whereas TkPath 0.3 doesn't. It might not work for both.

➌. Items, first only the tkpath items are discussed and therefrom pimage is omitted.

<text> ... </text>

ptext in Tkpath, text in Tk text window, ...tablelist.

Similar the canvas text item can be converted into SVG. The pathfont conversion is used to get the proper svg font names (always using), as a side-effect the Tk-font is reconstructed.

<rect />

prect in Tkpath, rect in Tk.

Straight translation. Similar Tk Canvas rect is simple to translate, by omitting rx and ry.

<circle />

circle in Tkpath, oval?

No direct Tk Canvas equivalent!

<ellipse />

ellipse in Tkpath, oval in Tk

Oval cannot be directly translated, the bounding box is to be mapped on rx and ry a ellipse.

<line />

pline in Tkpath.

<polyline />

polyline in Tkpath, line in Tk.

spline interpolated »line« cannot be translated to a polyline. For »-smooth« lines a path object is needed and the interpolation must be retrieved from the canvas window (other coordinates).

See also: path and can2svg.tcl (wrong implementation). Activated by tclspline. See recommended packages.

<polygon />

ppolygon in Tkpath, polygon in Tk.

Ppolygon requires TkPath 0.2.6 or higher.

spline interpolated Tk polygon require a translation identical to »line«. It is thus not feasible.

See also: line and path.

<path />

path in Tkpath.

The TkPath path item can be verbatim translated into a svg path object.

There is no direct Tk item matching path. Polygon, line and arc might however require path as their substitution. Access to the canvas internal interpolation is needed in order to map a »-smooth« object onto path.

Hence the discussed Tk elements are not covered by the first implementation.

Tk's arc can be translated to an path. –Not clear though from examples inside the

¹ h-150 horizontal line to 300,-150 Description says: rx ry x-axis-rotation large-arc-flag sweep-flag x y radius 150, x-axis 0, large-arc 1,0 no-sweep to point: 150, -150

center: 300,200 left: 150 ✔

Arc implementation is based on can2svg.tcl.

➍. Transformation Matrix: Only possible for TkPath and Zinc.

The simple transformation elements scale, translate, rotate and skew are not interesting here.

Gradient Transformations are defined as:

➎. Style

<style />

Class in Tk, Style in Tkpath.

Either as an external reference via CSS, or a property.

In general styles are defined inside a <defs/> section and then referenced via uri.

Important attributes font-size, font-style, font-weight, font-variant, text-decoration, visibility.

<defs/> are predefined for a group, that means whenever a group is generated a new <defs/> block must be generated, too.

referenced later as:

¹style do not work that way. Instead use contextual Style Sheets.

➏. image

<image />

pimage in Tkpath, icon in Zinc, image in Tk.

Only jpeg or png are generally supported. Will require tkpng on the Tk side.

FOP isn’t yet able to scale embedded images.

Base64 encoded images are possible with svg as seen inside OpenOffice. It does however require base64 and tkpng..

Two methods are used for images, unmodified images are stored inside the global <defs/> section and then referenced via the image name –similar to Tk. The second method registers, when an »pimage« image is modified via »-width« and »-height« properties. In cases where the image is modified a copy of that image is created and embedded straight away.

For modified images the »preserveAspectRatio« must be turned off.

Note 10/28/2008 - 16:51 : Zinc has a property »-tile« which uses an image to texture the shape of an item. This is mapped onto a <pattern/> element.

The best way to deal with image is through the »Img« package, but there are two cavets: - The screen-shot facility does not really work with Img 1.3 Tk 8.4 and Tiger –results are useless. - Img must be loaded as the first package, before any image is created, this may result in images without -data and without -file! The code generation detects this and generates proper images none-the-less. The Base64 package isn't needed for Img, Img encapsulates the data already in base64 –reliable.

Bitmaps: Don't use bitmaps!

Bitmaps cannot not be dealt with in SVG. A <use/> reference is added for bitmaps and thus allows for hand-crafted substitutions. An example for this are the open and closed bitmaps inside the rtl_tree under AQUA. Both bitmaps are substituted with the AQUA compliant unicode glyphs.

➐. Additional Elements:

➑. Pattern

tile inside Zinc.

See commentary above concerning stipple. Pattern are used for -tile and -stipple.

In the future it might be extended to cover gstripes::stripes for performance and adjustment reasons as-well.

➒. <clipPath/>

clip inside Zinc.

➓. <marker/>

lastend, firstend in Zinc, arrow, arrowshape in Tk.

The arrows are implemented as markers and used via marker-start and marker-end.

This is a property of line, arc and curve.

The Process: The hierarchy is traversed and each notable window touched. The properties for each item and window are parsed and default values are filtered out. -vgcode-

The filtered properties are handed to dumper for transferring the values into a SVG compliant form. Typical unused Tk Canvas properties, depending on state, are filtered out. Dimensions, colors and transformations are converted into a SVG compliant form. -vgcode and dumper-

Whenever an asynchronous value is meet such as font, image, style gradient, stops: dumper is called for this element and the needed data stored for later reference. -dumper-

After filtering and transforming the properties for a given item, the item code generation gets invoked. Inside the code generation: the coordinates and possible some dimensions are transformed. The entire item is created by referencing extra elements (stored beforehand) and compiling a nested list with sub elements and attributes. -dumper-

Seen from SVG, there are elements and attributes, coordinates and properties are transformed to attributes. Exceptions are text, gradients and images. Images are base64 encoded and embedded –must use them as part of the SVG defs section (To-Do)–

Elements are: text either via tspan or directly for ptext. stops inside a gradient, style and gradients. Gradients are referenced, when used as a color. Styles are likewise referenced. The major point, thus are the definition of viewports for synthetic and real groups. The general process is to make a place holder for a group –if it is really a group.

Elements are asynchronous processed (as seen from svgdumper). The information, leading to an element, are stored inside the namespace itself.

The »dumper« feeds each element directly into the DOM tree. This way any graphical element wit sub elements can be handled properly. The collect process inside vgcode does not produce anything here. That is, the generated source is abandoned right away.

Later Implemented, matters of Discussion: • can2svg.tcl Creates a dash array for Tk Canvas items This code should be used by svgdumper.

Integrated (resolve::dash).

• can2svg.tcl Features code for arrow shapes. This code should be used by svgdumper, too.

The svgdumper code implements arrows the Zinc-way. An arrow is defined inside the <defs/> section and referenced. The used code differs sharply from the can2svg code (the can2svg code can't be correct).

↯ The stipple implementation is different to can2svg.tcl. In can2svg path objects are generated to mimic stipple. I see stipple as a crude way to gain transparency, and thus convert it to opacity instead. Maybe the can2svg stipple way should be accessible, too.

Does it as a pattern, and pattern are not really supported by SVG applications. Truly a feature for the future. Works with »Safari Public Beta 4.0«, tested!

↯ state and visibility. Done inside the properties section. However this is the first animation element, which should be implemented in order to get interactive SVG.

Recommended Packages:

This package can use various packages, if present. The first –obvious package– is gstripes from the Gestalt Items ( gstripes is needed for the font conversion.

base64 from the Tcl Standard Library. base64 is used to encode gif images, which will be placed in the generated SVG <defs/> section and included by <use/>.

base64 does not work well with Img based images. Hence the recommendation is tkpng or Tk 8.6.

Img, is used to take screenshots from black-box controls, such as AQUA controls, ttk controls. The »screenshot« facility is implemented and tested with 1.3 and Tk 8.4 under AQUA. Technically it does work, the result was however unusable. The Img generated images are base64 encoded with Img and embedded into SVG. In contrast to the base64 package it does work!

tclspline ( This code is needed to convert a Tk canvas spline polygone and line into a bezier path object.