Skip to content

Commit

Permalink
feat: add embed.go example
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
hhhapz committed Jul 5, 2021
1 parent 75cfd57 commit 7268772
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ A video describing how to use the package can be seen on YouTube at <http://www.
* bulletgraph: Bullet Graphs (via Stephen Few)
* colortab: Display SVG named colors with RGB values
* compx: Component diagrams
* embed: Embedding svgs within another
* flower: Random "flowers"
* fontcompare: Compare two fonts
* f50: Get 50 photos from Flickr based on a query
Expand Down
100 changes: 100 additions & 0 deletions embed/embed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// embed -- including the contents of an SVG within your own
// +build !appengine

package main

import (
"encoding/xml"
"flag"
"fmt"
"io"
"os"

svg "github.com/ajstarks/svgo"
)

var (
canvas = svg.New(os.Stdout)
filename string
)

var (
titleHeight = 64
borderSize = 4
borderfmt = "fill:transparent;stroke:red;stroke-width:%d"
titlefmt = `text-anchor:middle;width:%d;font-size:32px`
groupfmt = `transform="translate(%d, %d)"`
)

func embed() error {
// load and parse svg
f, err := os.Open(filename)
if err != nil {
return err
}
s, err := parseSVG(f)
if err != nil {
return err
}
width := s.Width + 2*borderSize
height := s.Height + titleHeight + 2*borderSize
// create svg
canvas.Start(width, height)
placeHeader(width, height, f.Name())
// embed svg
placeSVG(s)
return nil
}

// SVG contains the parsed attributes and xml from the given file.
type SVG struct {
// Width and Height are attributes of the <svg> tag
Width int `xml:"width,attr"`
Height int `xml:"height,attr"`
// Doc is all all of the contents within the <svg> tags, specified by the
// `innerxml` struct tag
Doc []byte `xml:",innerxml"`
}

func parseSVG(src io.Reader) (SVG, error) {
var s SVG
data, err := io.ReadAll(src)
if err != nil {
return SVG{}, err
}
if xml.Unmarshal(data, &s); err != nil {
return SVG{}, err
}
return s, nil
}

func placeHeader(width, height int, name string) {
// add border
canvas.Rect(0, 0, width, height, fmt.Sprintf(borderfmt, borderSize))
// add title from file name
canvas.Text(width/2, titleHeight*3/4, name, fmt.Sprintf(titlefmt, width))
}

func placeSVG(s SVG) {
// create clip path of svg size
canvas.Group(`clip-path="url(#embed)"`, fmt.Sprintf(groupfmt, borderSize, titleHeight+borderSize))
canvas.ClipPath(`id="embed"`)
canvas.Rect(0, 0, s.Width, s.Height)
canvas.ClipEnd()
// append embedded svg
canvas.Writer.Write(s.Doc)
canvas.Gend()
canvas.End()
}

func init() {
flag.StringVar(&filename, "f", "embed.svg", "file name")
flag.Parse()
}

func main() {
if err := embed(); err != nil {
fmt.Fprintf(os.Stdout, "error: %v\n", err)
os.Exit(1)
}
}

0 comments on commit 7268772

Please sign in to comment.