Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add embed.go example #58

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
}
}