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.