SVG Converter

What is This?

This is a NewtonScript routine (not an application) that takes a Notes entry (paperroll stationery) and converts it into SVG code.

What’s it for?

Maybe it will grow into an application someday.

Some what’s left to do?

Well, the hardest part, believe it or not, is handling text and fonts.

  • SVG does not support text wrapping, so the converter will have to manually wrap the text.
  • It is hard to wrap the text when you don’t know how long each character is.
  • It is possible to embed the font into the SVG document, but that involves writing a Newton font-to-SVG converter. I’m not sure I really want to get that involved. (Though it is possible.) Then you’d be certain that the fonts in the SVG document render exactly as they do on the Newton.
  • Rich strings (text with inkWords mixed in) need to be handled too. I haven’t even looked at that yet.

The code

A few constants are in a different file, but you should get the idea.

func(frame roll)
begin
// Prepare the SVG header
local svg := kXMLDocTypeHeader;
svg := svg & kSVGTagStart;

// For each child in the paperroll entry
foreach item in roll.data do begin
// Default penWidth is 2.  If there's a viewFormat,
// parse out the penWidth from there.
local penWidth := 0;
if (item.viewFormat exists) then
//This extracts penWidth from viewFormat.
penWidth := Band(item.viewFormat >> 8, 15);
if (penWidth := 0) then penWidth := 2;

// Determine what kind of child it is.  If we have ink,
// go down the ink conversion route
if (item.ink exists) then begin
// We have ink.  Expand the ink to a strokeBundle.
strokeBundle := ExpandInk(item, 0);

// one stroke bundle can have more than one stroke.
// For instance, a "t" character would have two strokes for one
// character, but both strokes are in the same stroke bundle
num := CountStrokes(strokeBundle);

// Start the  group tag for this item
local path := "n";

// For each stroke, calculate the points
for i := 0 to num-1 do begin
stroke := GetStroke(strokeBundle, i);
points := GetStrokePointsArray(stroke, 0);
for j := 0 to Length(points)-1 by 2 do begin
y := points[j];
x := points[j+1];
if (j = 0) then
path := path & "tn";		//  the path Tag
end;
path := path & "n";		// Close the group tag
svg := svg & path;		// Append to the SVG document.
end else if (item.viewStationery = 'poly) then begin
// We have a polygon.  Process the polygon.  Extract the points
points := PointsToArray(item.points);

// points[0] is the polygon type. 0=circle
if (points[0] = 0) then begin
//Figure out the circle bounds and convert to a  tag.
w:=item.viewBounds.right - item.viewBounds.left;
h:=item.viewBounds.bottom - item.viewBounds.top;
r:=w/2;
cx:=item.viewBounds.left + r;
cy:=item.viewBounds.top + r;
local shape := "n";
svg := svg & shape;
end else if (points[0] = 1) then begin
// 1 = elipse - convert to an  tag
w:=item.viewBounds.right - item.viewBounds.left;
h:=item.viewBounds.bottom - item.viewBounds.top;
rx:=w/2;
ry:=h/2;
cx:=item.viewBounds.left + rx;
cy:=item.viewBounds.top + ry;
local shape := "n";
svg := svg & shape;
end else begin
// Everything else, convert to a path tag.
local shape := "n"; //first iteration already has M, others are L.
shape := shape & "t 2) then shape := shape & "L";
shape := shape & x & "," & y & " ";
end; //tells the  tag to return to the start (close)
if (closedPath) then shape := shape & "Z";

shape := shape & "\"/>n";
shape := shape & "n";
svg := svg & shape;
end;

end else if (item.viewStationery = 'para) then begin
//process a paragraph item (text)
//TODO: Figure out what the heck to do here.
local x := item.viewBounds.left;
local y := item.viewBounds.bottom;
local text := "" & item.text & "n";
svg := svg & text;
end;
end;
svg := svg & kSVGTagEnd;
return svg;
end

How does it look

Here is an example SVG file:

Just an example of what the SVG converter routine does. This has been modified a bit in Inkscape as part of my development efforts to figure out the the text stuff.