Skip to content

Commit 7268772

Browse files
committed
feat: add embed.go example
This commit adds the embed.go example, which focuses on demonstrating how to embed an svg within another. The example adds a title and a red border around the svg file provided via the -f argument. Closes ajstarks#57.
1 parent 75cfd57 commit 7268772

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed

README.markdown

+1
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ A video describing how to use the package can be seen on YouTube at <http://www.
149149
* bulletgraph: Bullet Graphs (via Stephen Few)
150150
* colortab: Display SVG named colors with RGB values
151151
* compx: Component diagrams
152+
* embed: Embedding svgs within another
152153
* flower: Random "flowers"
153154
* fontcompare: Compare two fonts
154155
* f50: Get 50 photos from Flickr based on a query

embed/embed.go

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// embed -- including the contents of an SVG within your own
2+
// +build !appengine
3+
4+
package main
5+
6+
import (
7+
"encoding/xml"
8+
"flag"
9+
"fmt"
10+
"io"
11+
"os"
12+
13+
svg "github.com/ajstarks/svgo"
14+
)
15+
16+
var (
17+
canvas = svg.New(os.Stdout)
18+
filename string
19+
)
20+
21+
var (
22+
titleHeight = 64
23+
borderSize = 4
24+
borderfmt = "fill:transparent;stroke:red;stroke-width:%d"
25+
titlefmt = `text-anchor:middle;width:%d;font-size:32px`
26+
groupfmt = `transform="translate(%d, %d)"`
27+
)
28+
29+
func embed() error {
30+
// load and parse svg
31+
f, err := os.Open(filename)
32+
if err != nil {
33+
return err
34+
}
35+
s, err := parseSVG(f)
36+
if err != nil {
37+
return err
38+
}
39+
width := s.Width + 2*borderSize
40+
height := s.Height + titleHeight + 2*borderSize
41+
// create svg
42+
canvas.Start(width, height)
43+
placeHeader(width, height, f.Name())
44+
// embed svg
45+
placeSVG(s)
46+
return nil
47+
}
48+
49+
// SVG contains the parsed attributes and xml from the given file.
50+
type SVG struct {
51+
// Width and Height are attributes of the <svg> tag
52+
Width int `xml:"width,attr"`
53+
Height int `xml:"height,attr"`
54+
// Doc is all all of the contents within the <svg> tags, specified by the
55+
// `innerxml` struct tag
56+
Doc []byte `xml:",innerxml"`
57+
}
58+
59+
func parseSVG(src io.Reader) (SVG, error) {
60+
var s SVG
61+
data, err := io.ReadAll(src)
62+
if err != nil {
63+
return SVG{}, err
64+
}
65+
if xml.Unmarshal(data, &s); err != nil {
66+
return SVG{}, err
67+
}
68+
return s, nil
69+
}
70+
71+
func placeHeader(width, height int, name string) {
72+
// add border
73+
canvas.Rect(0, 0, width, height, fmt.Sprintf(borderfmt, borderSize))
74+
// add title from file name
75+
canvas.Text(width/2, titleHeight*3/4, name, fmt.Sprintf(titlefmt, width))
76+
}
77+
78+
func placeSVG(s SVG) {
79+
// create clip path of svg size
80+
canvas.Group(`clip-path="url(#embed)"`, fmt.Sprintf(groupfmt, borderSize, titleHeight+borderSize))
81+
canvas.ClipPath(`id="embed"`)
82+
canvas.Rect(0, 0, s.Width, s.Height)
83+
canvas.ClipEnd()
84+
// append embedded svg
85+
canvas.Writer.Write(s.Doc)
86+
canvas.Gend()
87+
canvas.End()
88+
}
89+
90+
func init() {
91+
flag.StringVar(&filename, "f", "embed.svg", "file name")
92+
flag.Parse()
93+
}
94+
95+
func main() {
96+
if err := embed(); err != nil {
97+
fmt.Fprintf(os.Stdout, "error: %v\n", err)
98+
os.Exit(1)
99+
}
100+
}

0 commit comments

Comments
 (0)