Skip to content

Commit 703078d

Browse files
committed
Add a BuildSVG function
1 parent 342c9f5 commit 703078d

File tree

3 files changed

+84
-47
lines changed

3 files changed

+84
-47
lines changed

‎canvas.go‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ func (c *Canvas) String() string {
8888
return buffer.String()
8989
}
9090

91+
func (c *Canvas) heightScreen() int {
92+
return c.Height*16 + 8 + 1
93+
}
94+
95+
func (c *Canvas) widthScreen() int {
96+
return (c.Width + 1) * 8
97+
}
98+
9199
func (c *Canvas) runeAt(i Index) rune {
92100
if val, ok := c.data[i]; ok {
93101
return val
@@ -264,6 +272,36 @@ const (
264272
W // West
265273
)
266274

275+
func (c *Canvas) WriteSVGBody(dst io.Writer) {
276+
writeBytes(dst, "<g transform='translate(8,16)'>\n")
277+
278+
for _, l := range c.Lines() {
279+
l.Draw(dst)
280+
}
281+
282+
for _, t := range c.Triangles() {
283+
t.Draw(dst)
284+
}
285+
286+
for _, c := range c.RoundedCorners() {
287+
c.Draw(dst)
288+
}
289+
290+
for _, c := range c.Circles() {
291+
c.Draw(dst)
292+
}
293+
294+
for _, b := range c.Bridges() {
295+
b.Draw(dst)
296+
}
297+
298+
for _, t := range c.Text() {
299+
t.Draw(dst)
300+
}
301+
302+
writeBytes(dst, "</g>\n")
303+
}
304+
267305
// Lines returns a slice of all Line drawables that we can detect -- in all
268306
// possible orientations.
269307
func (c *Canvas) Lines() []Line {

‎examples_test.go‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func TestExamplesStableOutput(t *testing.T) {
4343
t.Fatal(err)
4444
}
4545
var out bytes.Buffer
46-
ASCIItoSVG(in, &out)
46+
BuildAndWriteSVG(in, &out)
4747
if i > 0 && previous != out.String() {
4848
c.Fail()
4949
}
@@ -59,14 +59,14 @@ func TestExamples(t *testing.T) {
5959

6060
for _, fileInfo := range fileInfos {
6161
in, out := getInOut(t, fileInfo.Name())
62-
ASCIItoSVG(in, out)
62+
BuildAndWriteSVG(in, out)
6363
}
6464
}
6565

6666
func BenchmarkComplicated(b *testing.B) {
6767
in, out := getInOut(b, "complicated.txt")
6868
b.ResetTimer()
6969
for i := 0; i < b.N; i++ {
70-
ASCIItoSVG(in, out)
70+
BuildAndWriteSVG(in, out)
7171
}
7272
}

‎svg.go‎

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,66 @@
11
package goat
22

33
import (
4+
"bytes"
45
"fmt"
56
"io"
67
)
78

8-
// ASCIItoSVG reads in a newline-delimited ASCII diagram and writes a
9-
// corresponding SVG diagram.
10-
func ASCIItoSVG(in io.Reader, out io.Writer) {
11-
canvas := NewCanvas(in)
9+
type SVG struct {
10+
Body []byte
11+
Width int
12+
Height int
13+
}
1214

13-
// Preamble
14-
writeBytes(&out,
15-
"<svg class='%s' xmlns='%s' version='%s' height='%d' width='%d'>\n",
15+
func (s SVG) String() string {
16+
return fmt.Sprintf("<svg class='%s' xmlns='%s' version='%s' height='%d' width='%d'>\n%s</svg>\n",
1617
"diagram",
1718
"http://www.w3.org/2000/svg",
18-
"1.1",
19-
canvas.Height*16+8+1, (canvas.Width+1)*8,
20-
)
21-
22-
writeBytes(&out, "<g transform='translate(8,16)'>\n")
23-
24-
for _, l := range canvas.Lines() {
25-
l.Draw(out)
26-
}
19+
"1.1", s.Height, s.Width, s.Body)
20+
}
2721

28-
for _, t := range canvas.Triangles() {
29-
t.Draw(out)
22+
// BuildSVG reads in a newline-delimited ASCII diagram from src and returns a SVG.
23+
func BuildSVG(src io.Reader) SVG {
24+
var buff bytes.Buffer
25+
canvas := NewCanvas(src)
26+
canvas.WriteSVGBody(&buff)
27+
return SVG{
28+
Body: buff.Bytes(),
29+
Width: canvas.widthScreen(),
30+
Height: canvas.heightScreen(),
3031
}
32+
}
3133

32-
for _, c := range canvas.RoundedCorners() {
33-
c.Draw(out)
34-
}
34+
// BuildAndWriteSVG reads in a newline-delimited ASCII diagram from src and writes a
35+
// corresponding SVG diagram to dst.
36+
func BuildAndWriteSVG(src io.Reader, dst io.Writer) {
37+
canvas := NewCanvas(src)
3538

36-
for _, c := range canvas.Circles() {
37-
c.Draw(out)
38-
}
39-
40-
for _, b := range canvas.Bridges() {
41-
b.Draw(out)
42-
}
39+
// Preamble
40+
writeBytes(dst,
41+
"<svg class='%s' xmlns='%s' version='%s' height='%d' width='%d'>\n",
42+
"diagram",
43+
"http://www.w3.org/2000/svg",
44+
"1.1",
45+
canvas.heightScreen(), canvas.widthScreen(),
46+
)
4347

44-
for _, t := range canvas.Text() {
45-
t.Draw(out)
46-
}
48+
canvas.WriteSVGBody(dst)
4749

48-
writeBytes(&out, "</g>\n")
49-
writeBytes(&out, "</svg>\n")
50+
writeBytes(dst, "</svg>\n")
5051
}
5152

52-
func writeBytes(out *io.Writer, format string, args ...interface{}) {
53+
func writeBytes(out io.Writer, format string, args ...interface{}) {
5354
bytesOut := fmt.Sprintf(format, args...)
5455

55-
_, err := (*out).Write([]byte(bytesOut))
56-
56+
_, err := out.Write([]byte(bytesOut))
5757
if err != nil {
5858
panic(nil)
5959
}
6060
}
6161

6262
// Draw a straight line as an SVG path.
6363
func (l Line) Draw(out io.Writer) {
64-
6564
start := l.start.asPixel()
6665
stop := l.stop.asPixel()
6766

@@ -140,7 +139,7 @@ func (l Line) Draw(out io.Writer) {
140139
}
141140
}
142141

143-
writeBytes(&out,
142+
writeBytes(out,
144143
"<path d='M %d,%d L %d,%d' style='fill:none;stroke:#000;'></path>\n",
145144
start.x, start.y,
146145
stop.x, stop.y,
@@ -243,7 +242,7 @@ func (t Triangle) Draw(out io.Writer) {
243242
}
244243
}
245244

246-
writeBytes(&out,
245+
writeBytes(out,
247246
"<polygon points='%f,%f %f,%f %f,%f' style='fill:#000' transform='rotate(%f, %f, %f)'></polygon>\n",
248247
x0, y0,
249248
x1, y1,
@@ -263,7 +262,7 @@ func (c *Circle) Draw(out io.Writer) {
263262

264263
pixel := c.start.asPixel()
265264

266-
writeBytes(&out,
265+
writeBytes(out,
267266
"<circle cx='%d' cy='%d' r='6' style='fill:%s;stroke:#000;'></circle>\n",
268267
pixel.x,
269268
pixel.y,
@@ -292,7 +291,7 @@ func (t Text) Draw(out io.Writer) {
292291
}
293292

294293
if opacity != 0 {
295-
writeBytes(&out,
294+
writeBytes(out,
296295
"<rect x='%d' y='%d' width='8' height='16' fill='rgb(%d,%d,%d)'></rect>",
297296
p.x-4, p.y-8,
298297
opacity, opacity, opacity,
@@ -310,7 +309,7 @@ func (t Text) Draw(out io.Writer) {
310309
c = "&lt;"
311310
}
312311

313-
writeBytes(&out,
312+
writeBytes(out,
314313
"<text text-anchor='middle' font-family='Menlo,Lucida Console,monospace' x='%d' y='%d' style='fill:#000;font-size:1em'>%s</text>\n",
315314
p.x, p.y+4, c,
316315
)
@@ -348,7 +347,7 @@ func (c *RoundedCorner) Draw(out io.Writer) {
348347
endY = y
349348
}
350349

351-
writeBytes(&out,
350+
writeBytes(out,
352351
"<path d='M %d,%d A 16,16 0 0,%d %d,%d' style='fill:none;stroke:#000;'></path>\n",
353352
startX,
354353
startY,
@@ -367,7 +366,7 @@ func (b Bridge) Draw(out io.Writer) {
367366
sweepFlag = 0
368367
}
369368

370-
writeBytes(&out,
369+
writeBytes(out,
371370
"<path d='M %d,%d A 9,9 0 0,%d %d,%d' style='fill:none;stroke:#000;'></path>\n",
372371
x, y-8,
373372
sweepFlag,

0 commit comments

Comments
 (0)