svg2jdor


svg2jdor


SVG2JDOR writes the JDOR commands that draw an SVG. JDOR (Java drawing for ooRexx) is Rony G. Flatscher's command handler in BSF4ooRexx850: a Rexx program draws on a bitmap with commands named after the methods of java.awt.Graphics2D. svg2jdor is the other half of jdor2svg: it reads an SVG and writes the commands, as few and as readable as they can be, one per line, as a macro. Or, with --rexx, as a Rexx program that draws the picture with JDOR and shows it.

rexx svg2jdor logo.svg              -- writes logo.jdor
rexx svg2jdor --rexx logo.svg       -- writes logo.rxj; rexx logo.rxj shows it

Usage

[rexx] svg2jdor [options] drawing.svg [macro.jdor | -]

The macro goes beside the SVG, with the extension .jdor (.rxj with --rexx), unless another file is given; - writes it to the standard output. svg2jdor then lists what it left out (see What Is Left Out).

When called without arguments, svg2jdor displays help information and exits.

Options


-h, --help Display help and exit
-q, --quiet Do not list what was left out
--rexx Write a Rexx program (.rxj) instead of a macro


What It Writes

A small SVG,

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="120">
  <rect x="10" y="10" width="80" height="50" fill="gold" stroke="navy" stroke-width="3"/>
  <circle cx="140" cy="40" r="25.5" fill="#f00" fill-opacity=".5"/>
  <text x="120" y="100" font-family="Arial" font-size="14" font-weight="bold">Hi</text>
</svg>

becomes

newImage 200 120
color gold 255 215 0
moveTo 10 10
fillRect 80 50
stroke ST1 3 CAP_BUTT JOIN_MITER 4
color navy 0 0 128
moveTo 10 10
drawRect 80 50
color red_a128 255 0 0 128
shape S1 Ellipse2D 114.5 14.5 51 51
fillShape S1
font F1 Arial-BOLD-14
color black 0 0 0
moveTo 120 100
drawString Hi
  • The transform in force is written whole (transform tx ty sx sy shx shy, or transform RESET), and only when it changes. The viewBox, the transform attributes, use and nested svg elements all end up in it.
  • Colours, strokes, fonts and gradients get a name the first time they are used, and are called by it after that. A colour is named after its CSS name when it has one (gold), else after its value (rgb_ff8000); an alpha is added to the name (red_a128).
  • A shape whose numbers are whole goes to the primitives (moveTo + fillRect, fillOval, fillRoundRect, drawLine, fillPolygon, drawPolyline...); any other one to a named shape (Rectangle2D, Ellipse2D, RoundRectangle2D, Line2D, Path2D), named after the element's id when it has one.
  • A path of one piece, of straight lines and whole numbers, becomes a line, a rectangle or a polygon. Arcs become cubic curves.
  • An element with an id gets a comment (-- path #wave).

Some numbers are whole in JDOR: the width of a stroke, the font size, the position of a string. A fractional one is drawn exactly all the same: under a transform scaled by the fraction, with the shape, the dashes or the position divided by it. A font is written with its style and size (Arial-BOLD-14): when Java does not have the font, JDOR decodes the name, and keeps the style and the size.

What Is Read

  • Shapes: rect (with rx/ry too), circle, ellipse, line, polyline, polygon, and path, with all of its syntax (relative commands, H/V, the smooth curves S/T, arcs).
  • Text: text and tspan (lines with x, y, dx, dy), with the font's family, size, weight and style. The generic families become Java's logical fonts (serif → Serif, sans-serif → SansSerif, monospace → Monospaced).
  • Structure: g, a, switch, use (of an element or a symbol), nested svg, defs; the viewBox and preserveAspectRatio; display and visibility.
  • Transforms: matrix, translate, scale, rotate (with its centre too), skewX, skewY.
  • Paint: colours (names, #rgb, #rrggbb, with alpha too, rgb(), rgba(), hsl(), hsla(), currentColor), fill-opacity, stroke-opacity and opacity (folded into the colours' alpha), fill-rule, the stroke's width, caps, joins, miter limit, dashes and their offset.
  • Linear gradients, with href, both gradientUnits, gradientTransform and spreadMethod. JDOR's gradient has two colours: it keeps the first and the last stops. A gradient that the bounding box stretches out of square is drawn in its own space, with the shape mapped into it, so that it comes out as the SVG has it.
  • Clips: clip-path with a clipPath of shapes, in both clipPathUnits. It is drawn between pushGC and popGC; several shapes become an Area, their union.
  • CSS: the presentation attributes, the style attribute, and the rules of a <style> sheet whose selectors are tags, .class, #id, those together (rect.big), and those with descendant () and child (>) combinators between them. Specificity and order are respected.

What Is Left Out

  • Masks, filters, patterns, markers, radial gradients (drawn with their first colour), images, textPath, foreignObject, animation.
  • CSS selectors other than the ones above (:hover, [attr], +, ~), and @ rules.
  • A gradient on text is drawn with its last colour; a gradient on a stroke out of square has its ends mapped, but its isolines stay square.

Text width. JDOR measures text only when it runs, with the fonts of the machine: a macro cannot. So text-anchor (middle, end), and a tspan that goes on along a line after other text, are placed with an estimate of the width (Helvetica's, or 0.6 em in a monospaced font), and said so. With --rexx, the program measures each anchored text with stringBounds before drawing it, and places it exactly.

The Rexx Program

With --rexx, svg2jdor writes a program for BSF4ooRexx850, in the style of the JDOR samples: it creates the JDOR handler, draws the picture, shows it in a window, and lists any error. rexx drawing.rxj ? also shows the JDOR commands as they run.

The Way Back

jdor2svg turns the macro into SVG again. Of an SVG that svg2jdor reads whole, the way there and back gives the same picture.