@@ 1,54 @@
+// generated by go run gen.go; DO NOT EDIT
+
+package giologo
+
+var Gio = []byte{
+ 0x89, 0x49, 0x56, 0x47, 0x02, 0x0a, 0x00, 0x50, 0x50, 0xb0, 0xb0, 0x80, 0x80, 0xc0, 0x19, 0x88,
+ 0xe5, 0x69, 0xbf, 0x21, 0x80, 0x3d, 0x80, 0x31, 0x80, 0x91, 0x80, 0x29, 0x80, 0xc5, 0x80, 0xe1,
+ 0x7f, 0xb9, 0x80, 0x71, 0x7f, 0x05, 0x81, 0xd9, 0x7e, 0x35, 0x81, 0xc9, 0x7c, 0x0d, 0x81, 0xad,
+ 0x79, 0x71, 0x82, 0xc5, 0x76, 0x25, 0x84, 0x95, 0x7e, 0xd5, 0x80, 0x35, 0x7d, 0xc1, 0x81, 0xe9,
+ 0x7b, 0xc1, 0x82, 0xb1, 0x7c, 0x8d, 0x82, 0xcd, 0x79, 0xa5, 0x85, 0x15, 0x78, 0x6d, 0x89, 0x45,
+ 0x7f, 0xa1, 0x81, 0xc5, 0x7e, 0x5d, 0x83, 0x8d, 0x7e, 0x21, 0x85, 0xd9, 0x7f, 0x51, 0x81, 0xd1,
+ 0x7f, 0xa5, 0x82, 0xf9, 0x7f, 0xf9, 0x83, 0x2d, 0x80, 0x69, 0x81, 0x99, 0x80, 0xcd, 0x82, 0x51,
+ 0x81, 0x09, 0x84, 0x8d, 0x80, 0xf1, 0x80, 0x39, 0x81, 0xcd, 0x81, 0x0d, 0x82, 0x85, 0x82, 0x86,
+ 0x95, 0x82, 0x31, 0x87, 0xc9, 0x83, 0xdd, 0x8a, 0x39, 0x84, 0xd9, 0x82, 0x59, 0x80, 0x89, 0x85,
+ 0x35, 0x80, 0x1d, 0x88, 0xb1, 0x7f, 0x21, 0x83, 0x65, 0x7f, 0x99, 0x86, 0xd1, 0x7e, 0xa9, 0x88,
+ 0x69, 0x7c, 0xb1, 0x80, 0x35, 0x7f, 0x19, 0x81, 0x25, 0x7e, 0x82, 0x2d, 0x7d, 0xd9, 0x7f, 0x65,
+ 0x7e, 0xd1, 0x7e, 0x21, 0x7d, 0x95, 0x7d, 0x3d, 0x7c, 0x85, 0x7f, 0xa9, 0x7f, 0x7e, 0x5d, 0x7f,
+ 0x71, 0x7e, 0x31, 0x7f, 0xe5, 0x7f, 0xf9, 0x7f, 0xc9, 0x7f, 0xf1, 0x7f, 0xad, 0x7f, 0xe5, 0x7f,
+ 0xbf, 0x9d, 0x7f, 0xd5, 0x7f, 0x55, 0x7f, 0x71, 0x7f, 0x41, 0x7f, 0x09, 0x7f, 0xf1, 0x7f, 0xa1,
+ 0x7f, 0x05, 0x80, 0x45, 0x7f, 0x3d, 0x80, 0x05, 0x7f, 0x81, 0x80, 0x65, 0x7f, 0x21, 0x81, 0x69,
+ 0x7f, 0xc5, 0x81, 0x9d, 0x7f, 0xb9, 0x80, 0x3d, 0x80, 0x69, 0x81, 0x95, 0x80, 0x11, 0x82, 0xf9,
+ 0x80, 0x05, 0x81, 0x9d, 0x80, 0xfd, 0x81, 0x55, 0x81, 0xb9, 0x82, 0x41, 0x82, 0xd9, 0x80, 0x0d,
+ 0x81, 0x85, 0x81, 0x3d, 0x82, 0xd5, 0x81, 0x59, 0x83, 0x81, 0x80, 0xbd, 0x81, 0x49, 0x80, 0xa1,
+ 0x83, 0x81, 0x7f, 0x41, 0x85, 0x2d, 0x7f, 0xb1, 0x81, 0xb1, 0x7d, 0x45, 0x83, 0x61, 0x7c, 0x41,
+ 0x84, 0x6d, 0x7e, 0x31, 0x81, 0x95, 0x7c, 0x41, 0x82, 0xf9, 0x7a, 0xd5, 0x82, 0xf9, 0x7c, 0x19,
+ 0x81, 0xcd, 0x79, 0xb1, 0x81, 0x0d, 0x77, 0xa5, 0x81, 0xa9, 0x7b, 0xed, 0x7f, 0xb9, 0x76, 0x71,
+ 0x7e, 0x31, 0x73, 0x8d, 0x7c, 0xa9, 0x7d, 0xc1, 0x7e, 0x99, 0x7b, 0x15, 0x7d, 0x05, 0x7a, 0x09,
+ 0x7b, 0xcd, 0x7d, 0x2d, 0x7d, 0xcd, 0x7c, 0x29, 0x79, 0xe5, 0x7c, 0xfd, 0x75, 0x21, 0x80, 0x89,
+ 0x7b, 0x11, 0x82, 0xb1, 0x76, 0x61, 0x84, 0x79, 0x73, 0xf1, 0x81, 0x51, 0x7d, 0x69, 0x84, 0x76,
+ 0x15, 0x87, 0x09, 0x79, 0x51, 0x83, 0x91, 0x7d, 0x8e, 0x9d, 0x7b, 0xd5, 0x8a, 0x09, 0x7a, 0xb1,
+ 0x71, 0x81, 0x69, 0x7f, 0xe9, 0x82, 0xe1, 0x7e, 0x69, 0x84, 0x65, 0x7e, 0x9d, 0x80, 0xd1, 0x7f,
+ 0x49, 0x81, 0x31, 0x80, 0x8d, 0x81, 0x9d, 0x80, 0xe1, 0x80, 0x80, 0xc0, 0x45, 0x7b, 0x59, 0x82,
+ 0xbb, 0x75, 0x80, 0x25, 0x80, 0xb9, 0x80, 0x95, 0x80, 0xd5, 0x80, 0x05, 0x81, 0x5d, 0x80, 0x65,
+ 0x81, 0xed, 0x80, 0xb5, 0x82, 0x59, 0x81, 0x11, 0x84, 0x1d, 0x80, 0x59, 0x80, 0x39, 0x80, 0xb1,
+ 0x80, 0x3d, 0x80, 0x0d, 0x81, 0xe9, 0x7f, 0x91, 0x80, 0x7d, 0x7f, 0x82, 0x35, 0x7f, 0x7d, 0x81,
+ 0xc9, 0x7f, 0x61, 0x80, 0x91, 0x7f, 0xcd, 0x80, 0x35, 0x7f, 0x11, 0x81, 0xe1, 0x7f, 0x19, 0x80,
+ 0xbd, 0x7f, 0xe9, 0x7f, 0xa1, 0x7f, 0xd5, 0x7f, 0x75, 0x7f, 0x9d, 0x7f, 0x7e, 0x1d, 0x7f, 0x81,
+ 0x7e, 0xad, 0x7e, 0xc1, 0x7f, 0xc9, 0x7f, 0x8d, 0x7f, 0x7d, 0x7f, 0x95, 0x7f, 0x29, 0x7f, 0xf5,
+ 0x7f, 0x11, 0x7f, 0x19, 0x80, 0x21, 0x7e, 0x29, 0x80, 0x35, 0x7d, 0x0d, 0x80, 0x4d, 0x7f, 0x1d,
+ 0x80, 0x99, 0x7e, 0x1d, 0x80, 0xe5, 0x7d, 0x80, 0x99, 0x7f, 0x11, 0x80, 0x29, 0x7f, 0x5d, 0x80,
+ 0xdd, 0x7e, 0x3d, 0x80, 0xc5, 0x7f, 0x95, 0x80, 0xa9, 0x7f, 0xe5, 0x80, 0xc5, 0x7f, 0xe1, 0x80,
+ 0x80, 0xc0, 0x69, 0x84, 0x59, 0x84, 0xb3, 0x29, 0x7f, 0x75, 0x80, 0xc9, 0x7e, 0x89, 0x81, 0xf5,
+ 0x7e, 0x71, 0x82, 0x19, 0x80, 0x7d, 0x80, 0xad, 0x80, 0x91, 0x80, 0x19, 0x81, 0x95, 0x80, 0x5d,
+ 0x80, 0x05, 0x80, 0xc5, 0x80, 0xe5, 0x7f, 0xdd, 0x80, 0x81, 0x7f, 0x3d, 0x80, 0xf5, 0x7e, 0xd9,
+ 0x7f, 0x7c, 0x1d, 0x7f, 0x7d, 0x7d, 0xe3, 0xf9, 0x7f, 0xf5, 0x7d, 0xb7, 0x21, 0x81, 0xd9, 0x7f,
+ 0x51, 0x82, 0x05, 0x80, 0x49, 0x83, 0xa1, 0x80, 0xd9, 0x80, 0x89, 0x80, 0x79, 0x81, 0x69, 0x81,
+ 0x9d, 0x81, 0x65, 0x82, 0x31, 0x80, 0x81, 0x81, 0xad, 0x7f, 0x1d, 0x83, 0x95, 0x7e, 0x2d, 0x84,
+ 0x15, 0x7f, 0xe9, 0x80, 0xbd, 0x7d, 0x45, 0x81, 0x75, 0x7c, 0x11, 0x81, 0xbd, 0x7e, 0xcd, 0x7f,
+ 0x79, 0x7d, 0x29, 0x7f, 0xd9, 0x7c, 0x7c, 0x59, 0x7f, 0xcd, 0x7e, 0x85, 0x7f, 0x4d, 0x7d, 0x19,
+ 0x80, 0x1d, 0x7c, 0x8d, 0x80, 0xe5, 0x7e, 0x8d, 0x81, 0xe9, 0x7d, 0xcd, 0x82, 0xad, 0x7d, 0x21,
+ 0x80, 0xfd, 0x7f, 0x3d, 0x80, 0xf9, 0x7f, 0x5d, 0x80, 0xf9, 0x7f, 0xe1,
+}
+
+// In total, 2912 SVG bytes in 1 files converted to 732 IconVG bytes.
@@ 1,524 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import (
+ "bytes"
+ "encoding/xml"
+ "flag"
+ "fmt"
+ "go/format"
+ "image/color"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "sort"
+ "strconv"
+ "strings"
+
+ "golang.org/x/exp/shiny/iconvg"
+ "golang.org/x/image/math/f32"
+)
+
+var outDir = flag.String("o", "", "output directory")
+var pkgName = flag.String("pkg", "icons", "package name")
+
+var (
+ out = new(bytes.Buffer)
+ failures = []string{}
+ varNames = []string{}
+
+ totalFiles int
+ totalIVGBytes int
+ totalSVGBytes int
+)
+
+func upperCase(s string) string {
+ if c := s[0]; 'a' <= c && c <= 'z' {
+ return string(c-0x20) + s[1:]
+ }
+ return s
+}
+
+func main() {
+ flag.Parse()
+ args := flag.Args()
+ if len(args) < 1 {
+ fmt.Fprintf(os.Stderr, "please provide a directory to convert\n")
+ os.Exit(2)
+ }
+ iconsDir := args[0]
+
+ out.WriteString("// generated by go run gen.go; DO NOT EDIT\n\npackage ")
+ out.WriteString(*pkgName)
+ out.WriteString("\n\n")
+
+ if err := genDir(iconsDir); err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Fprintf(out,
+ "// In total, %d SVG bytes in %d files converted to %d IconVG bytes.\n",
+ totalSVGBytes, totalFiles, totalIVGBytes)
+
+ if len(failures) != 0 {
+ out.WriteString("\n/*\nFAILURES:\n\n")
+ for _, failure := range failures {
+ out.WriteString(failure)
+ out.WriteByte('\n')
+ }
+ out.WriteString("\n*/")
+ }
+
+ if *outDir != "" {
+ if err := os.MkdirAll(*outDir, 0775); err != nil && !os.IsExist(err) {
+ log.Fatal(err)
+ }
+ }
+ raw := out.Bytes()
+ formatted, err := format.Source(raw)
+ if err != nil {
+ log.Fatalf("gofmt failed: %v\n\nGenerated code:\n%s", err, raw)
+ }
+ if err := ioutil.WriteFile(filepath.Join(*outDir, "data.go"), formatted, 0644); err != nil {
+ log.Fatalf("WriteFile failed: %s\n", err)
+ }
+
+ {
+ b := new(bytes.Buffer)
+ b.WriteString("// generated by go run genicons.go; DO NOT EDIT\n\npackage ")
+ b.WriteString(*pkgName)
+ b.WriteString("\n\n")
+ b.WriteString("var list = []struct{ name string; data []byte } {\n")
+ for _, v := range varNames {
+ fmt.Fprintf(b, "{%q, %s},\n", v, v)
+ }
+ b.WriteString("}\n\n")
+ raw := b.Bytes()
+ formatted, err := format.Source(raw)
+ if err != nil {
+ log.Fatalf("gofmt failed: %v\n\nGenerated code:\n%s", err, raw)
+ }
+ if err := ioutil.WriteFile(filepath.Join(*outDir, "data_test.go"), formatted, 0644); err != nil {
+ log.Fatalf("WriteFile failed: %s\n", err)
+ }
+ }
+}
+
+func genDir(dirName string) error {
+ fqSVGDirName := filepath.FromSlash(dirName)
+ f, err := os.Open(fqSVGDirName)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ infos, err := f.Readdir(-1)
+ if err != nil {
+ log.Fatal(err)
+ }
+ baseNames, fileNames, sizes := []string{}, map[string]string{}, map[string]int{}
+ for _, info := range infos {
+ name := info.Name()
+
+ nameParts := strings.Split(name, "_")
+ if len(nameParts) != 3 || nameParts[0] != "ic" {
+ continue
+ }
+ baseName := nameParts[1]
+ var size int
+ if n, err := fmt.Sscanf(nameParts[2], "%dpx.svg", &size); err != nil || n != 1 {
+ continue
+ }
+ if prevSize, ok := sizes[baseName]; ok {
+ if size > prevSize {
+ fileNames[baseName] = name
+ sizes[baseName] = size
+ }
+ } else {
+ fileNames[baseName] = name
+ sizes[baseName] = size
+ baseNames = append(baseNames, baseName)
+ }
+ }
+
+ sort.Strings(baseNames)
+ for _, baseName := range baseNames {
+ fileName := fileNames[baseName]
+ path := filepath.Join(dirName, fileName)
+ f, err := ioutil.ReadFile(path)
+ if err != nil {
+ failures = append(failures, fmt.Sprintf("%s: %v", path, err))
+ continue
+ }
+ if err = genFile(f, baseName, float32(sizes[baseName])); err != nil {
+ failures = append(failures, fmt.Sprintf("%s: %v", path, err))
+ continue
+ }
+ }
+ return nil
+}
+
+type SVG struct {
+ Width string `xml:"width,attr"`
+ Height string `xml:"height,attr"`
+ Fill string `xml:"fill,attr"`
+ ViewBox string `xml:"viewBox,attr"`
+ Paths []*Path `xml:"path"`
+ // Some of the SVG files contain <circle> elements, not just <path>
+ // elements. IconVG doesn't have circles per se. Instead, we convert such
+ // circles to paired arcTo commands, tacked on to the first path.
+ //
+ // In general, this isn't correct if the circles and the path overlap, but
+ // that doesn't happen in the specific case of the Material Design icons.
+ Circles []Circle `xml:"circle"`
+}
+
+type Path struct {
+ D string `xml:"d,attr"`
+ Fill string `xml:"fill,attr"`
+ FillOpacity *float32 `xml:"fill-opacity,attr"`
+ Opacity *float32 `xml:"opacity,attr"`
+
+ creg uint8
+}
+
+type Circle struct {
+ Cx float32 `xml:"cx,attr"`
+ Cy float32 `xml:"cy,attr"`
+ R float32 `xml:"r,attr"`
+}
+
+func genFile(svgData []byte, baseName string, outSize float32) error {
+ var varName string
+ for _, s := range strings.Split(baseName, "_") {
+ varName += upperCase(s)
+ }
+ fmt.Fprintf(out, "var %s = []byte{", varName)
+ defer fmt.Fprintf(out, "\n}\n\n")
+ varNames = append(varNames, varName)
+
+ g := &SVG{}
+ if err := xml.Unmarshal(svgData, g); err != nil {
+ return err
+ }
+
+ var vbx, vby, vbx2, vby2 float32
+ for i, v := range strings.Split(g.ViewBox, " ") {
+ f, err := strconv.ParseFloat(v, 32)
+ if err != nil {
+ return fmt.Errorf("genFile: failed to parse ViewBox (%q):", g.ViewBox, err)
+ }
+ switch i {
+ case 0:
+ vbx = float32(f)
+ case 1:
+ vby = float32(f)
+ case 2:
+ vbx2 = float32(f)
+ case 3:
+ vby2 = float32(f)
+ }
+ }
+ dx, dy := outSize, outSize
+ var size float32
+ if aspect := (vbx2 - vbx) / (vby2 - vby); aspect >= 1 {
+ dy /= aspect
+ size = vbx2 - vbx
+ } else {
+ dx /= aspect
+ size = vby2 - vby
+ }
+ palette := iconvg.DefaultPalette
+ pmap := make(map[color.RGBA]uint8)
+ for _, p := range g.Paths {
+ if p.Fill == "" {
+ p.Fill = g.Fill
+ }
+ c, err := parseColor(p.Fill)
+ if err != nil {
+ return err
+ }
+ var ok bool
+ if p.creg, ok = pmap[c]; !ok {
+ if len(pmap) == 64 {
+ panic("too many colors")
+ }
+ p.creg = uint8(len(pmap))
+ palette[p.creg] = c
+ pmap[c] = p.creg
+ }
+ }
+ var enc iconvg.Encoder
+ enc.Reset(iconvg.Metadata{
+ ViewBox: iconvg.Rectangle{
+ Min: f32.Vec2{-dx * .5, -dy * .5},
+ Max: f32.Vec2{+dx * .5, +dy * .5},
+ },
+ Palette: palette,
+ })
+
+ offset := f32.Vec2{
+ vbx * outSize / size,
+ vby * outSize / size,
+ }
+
+ // adjs maps from opacity to a cReg adj value.
+ adjs := map[float32]uint8{}
+
+ for _, p := range g.Paths {
+ if err := genPath(&enc, p, adjs, outSize, size, offset, g.Circles); err != nil {
+ return err
+ }
+ g.Circles = nil
+ }
+
+ if len(g.Circles) != 0 {
+ if err := genPath(&enc, &Path{}, adjs, outSize, size, offset, g.Circles); err != nil {
+ return err
+ }
+ g.Circles = nil
+ }
+
+ ivgData, err := enc.Bytes()
+ if err != nil {
+ return fmt.Errorf("iconvg encoding failed: %v", err)
+ }
+ for i, x := range ivgData {
+ if i&0x0f == 0x00 {
+ out.WriteByte('\n')
+ }
+ fmt.Fprintf(out, "%#02x, ", x)
+ }
+
+ totalFiles++
+ totalSVGBytes += len(svgData)
+ totalIVGBytes += len(ivgData)
+ return nil
+}
+
+func parseColor(col string) (color.RGBA, error) {
+ if col == "none" {
+ return color.RGBA{}, nil
+ }
+ if len(col) == 0 {
+ return color.RGBA{A: 0xff}, nil
+ }
+ if len(col) == 0 || col[0] != '#' {
+ return color.RGBA{}, fmt.Errorf("invalid color: %q", col)
+ }
+ col = col[1:]
+ if len(col) != 6 {
+ return color.RGBA{}, fmt.Errorf("invalid color length: %q", col)
+ }
+ elems := make([]byte, len(col)/2)
+ for i := range elems {
+ e, err := strconv.ParseUint(col[i*2:i*2+2], 16, 8)
+ if err != nil {
+ return color.RGBA{}, err
+ }
+ elems[i] = byte(e)
+ }
+ return color.RGBA{R: elems[0], G: elems[1], B: elems[2], A: 255}, nil
+}
+
+func genPath(enc *iconvg.Encoder, p *Path, adjs map[float32]uint8, outSize, size float32, offset f32.Vec2, circles []Circle) error {
+ adj := uint8(0)
+ opacity := float32(1)
+ if p.Opacity != nil {
+ opacity = *p.Opacity
+ } else if p.FillOpacity != nil {
+ opacity = *p.FillOpacity
+ }
+ if opacity != 1 {
+ var ok bool
+ if adj, ok = adjs[opacity]; !ok {
+ adj = uint8(len(adjs) + 1)
+ adjs[opacity] = adj
+ // Set CREG[0-adj] to be a blend of transparent (0x7f) and the
+ // first custom palette color (0x80).
+ enc.SetCReg(adj, false, iconvg.BlendColor(uint8(opacity*0xff), 0x7f, 0x80+p.creg))
+ }
+ } else {
+ enc.SetCReg(adj, false, iconvg.PaletteIndexColor(p.creg))
+ }
+
+ needStartPath := true
+ if p.D != "" {
+ needStartPath = false
+ if err := genPathData(enc, adj, p.D, outSize, size, offset); err != nil {
+ return err
+ }
+ }
+
+ for _, c := range circles {
+ // Normalize.
+ cx := c.Cx * outSize / size
+ cx -= outSize/2 + offset[0]
+ cy := c.Cy * outSize / size
+ cy -= outSize/2 + offset[1]
+ r := c.R * outSize / size
+
+ if needStartPath {
+ needStartPath = false
+ enc.StartPath(adj, cx-r, cy)
+ } else {
+ enc.ClosePathAbsMoveTo(cx-r, cy)
+ }
+
+ // Convert a circle to two relative arcTo ops, each of 180 degrees.
+ // We can't use one 360 degree arcTo as the start and end point
+ // would be coincident and the computation is degenerate.
+ enc.RelArcTo(r, r, 0, false, true, +2*r, 0)
+ enc.RelArcTo(r, r, 0, false, true, -2*r, 0)
+ }
+
+ enc.ClosePathEndPath()
+ return nil
+}
+
+func genPathData(enc *iconvg.Encoder, adj uint8, pathData string, outSize, size float32, offset f32.Vec2) error {
+ if strings.HasSuffix(pathData, "z") {
+ pathData = pathData[:len(pathData)-1]
+ }
+ r := strings.NewReader(pathData)
+
+ var args [7]float32
+ op, relative, started := byte(0), false, false
+ var count int
+ for {
+ b, err := r.ReadByte()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return err
+ }
+ count++
+
+ switch {
+ case b == ' ' || b == '\n' || b == '\t':
+ continue
+ case 'A' <= b && b <= 'Z':
+ op, relative = b, false
+ case 'a' <= b && b <= 'z':
+ op, relative = b, true
+ default:
+ r.UnreadByte()
+ }
+
+ n := 0
+ switch op {
+ case 'A', 'a':
+ n = 7
+ case 'L', 'l', 'T', 't':
+ n = 2
+ case 'Q', 'q', 'S', 's':
+ n = 4
+ case 'C', 'c':
+ n = 6
+ case 'H', 'h', 'V', 'v':
+ n = 1
+ case 'M', 'm':
+ n = 2
+ case 'Z', 'z':
+ default:
+ return fmt.Errorf("unknown opcode %c\n", b)
+ }
+
+ scan(&args, r, n)
+ normalize(&args, n, op, outSize, size, offset, relative)
+
+ switch op {
+ case 'A':
+ enc.AbsArcTo(args[0], args[1], args[2], args[3] != 0, args[4] != 0, args[5], args[6])
+ case 'a':
+ enc.RelArcTo(args[0], args[1], args[2], args[3] != 0, args[4] != 0, args[5], args[6])
+ case 'L':
+ enc.AbsLineTo(args[0], args[1])
+ case 'l':
+ enc.RelLineTo(args[0], args[1])
+ case 'T':
+ enc.AbsSmoothQuadTo(args[0], args[1])
+ case 't':
+ enc.RelSmoothQuadTo(args[0], args[1])
+ case 'Q':
+ enc.AbsQuadTo(args[0], args[1], args[2], args[3])
+ case 'q':
+ enc.RelQuadTo(args[0], args[1], args[2], args[3])
+ case 'S':
+ enc.AbsSmoothCubeTo(args[0], args[1], args[2], args[3])
+ case 's':
+ enc.RelSmoothCubeTo(args[0], args[1], args[2], args[3])
+ case 'C':
+ enc.AbsCubeTo(args[0], args[1], args[2], args[3], args[4], args[5])
+ case 'c':
+ enc.RelCubeTo(args[0], args[1], args[2], args[3], args[4], args[5])
+ case 'H':
+ enc.AbsHLineTo(args[0])
+ case 'h':
+ enc.RelHLineTo(args[0])
+ case 'V':
+ enc.AbsVLineTo(args[0])
+ case 'v':
+ enc.RelVLineTo(args[0])
+ case 'M':
+ if !started {
+ started = true
+ enc.StartPath(adj, args[0], args[1])
+ } else {
+ enc.ClosePathAbsMoveTo(args[0], args[1])
+ }
+ case 'm':
+ enc.ClosePathRelMoveTo(args[0], args[1])
+ }
+ }
+ return nil
+}
+
+func scan(args *[7]float32, r *strings.Reader, n int) {
+ for i := 0; i < n; i++ {
+ for {
+ if b, _ := r.ReadByte(); b != ' ' && b != ',' && b != '\n' && b != '\t' {
+ r.UnreadByte()
+ break
+ }
+ }
+ fmt.Fscanf(r, "%f", &args[i])
+ }
+}
+
+func normalize(args *[7]float32, n int, op byte, outSize, size float32, offset f32.Vec2, relative bool) {
+ for i := 0; i < n; i++ {
+ if (op == 'A' || op == 'a') && (i == 3 || i == 4) {
+ continue
+ }
+ args[i] *= outSize / size
+ if relative {
+ continue
+ }
+ if (op == 'A' || op == 'a') && i < 5 {
+ // For arcs, skip everything other than x, y.
+ continue
+ }
+ args[i] -= outSize / 2
+ switch {
+ case op == 'A' && i == 5: // Arc x.
+ args[i] -= offset[0]
+ case op == 'A' && i == 6: // Arc y.
+ args[i] -= offset[1]
+ case n != 1:
+ args[i] -= offset[i&0x01]
+ case op == 'H':
+ args[i] -= offset[0]
+ case op == 'V':
+ args[i] -= offset[1]
+ }
+ }
+}
@@ 1,1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><path id="path2" d="M171.134,10.115c0.706,1.277 1.031,3.018 0.85,4.053c-0.668,3.8 -3.02,5.433 -6.177,6.456c-17.173,5.565 -33.724,12.96 -49.238,22.051c-7.574,4.439 -14.895,9.297 -21.866,14.647c-17.701,13.585 -33.109,30.048 -42.288,50.274c-3.926,8.651 -6.584,17.9 -7.716,27.3c-0.84,6.98 -1.032,14.097 -0.165,21.183c0.922,7.526 3.168,14.914 6.982,21.473c2.919,5.02 6.541,9.614 10.953,13.397c16.009,13.726 38.348,20.202 57.903,22.535c15.197,1.813 29.539,1.052 43.283,-1.646c16.656,-3.271 35.205,-6.303 46.134,-19.15c3.637,-4.275 5.862,-9.958 5.366,-15.091c-0.832,-8.611 -6.318,-15.363 -12.911,-20.092c-2.547,-1.826 -5.3,-3.447 -8.319,-4.329c-0.596,-0.174 -1.199,-0.342 -1.759,-0.591c-2.067,-0.92 -3.61,-2.965 -3.963,-5.198c-0.309,-1.961 0.112,-3.916 1.237,-5.259c2.691,-3.211 6.011,-3.203 9.424,-2.112c3.849,1.23 7.512,3.078 10.996,5.136c5.441,3.214 10.553,7.091 14.52,11.986c4.536,5.6 8.044,11.92 9.72,17.837c2.628,9.28 1.529,19.312 -2.703,27.966c-4.406,9.012 -12.317,17.43 -19.292,22.706c-8.415,6.364 -18.268,11.999 -26.835,15.081c-16.145,5.809 -33.096,8.98 -47.79,8.718c-23.131,-0.413 -49.514,-8.324 -68.328,-18.39c-12.484,-6.679 -23.508,-15.565 -31.952,-26.468c-11.709,-15.117 -17.065,-36.463 -16.605,-53.416c0.646,-23.808 11.029,-49.666 23.321,-66.802c10.312,-14.375 23.526,-26.693 37.774,-37.166c17.675,-12.991 37.297,-23.386 57.737,-31.816c7.706,-3.178 15.527,-6.035 23.475,-8.547c3.247,-1.027 6.806,1.041 8.232,3.274Z"/><path id="path6" d="M102.759,140.491c2.404,0.748 3.816,3.067 4.414,5.416c1.88,7.39 4.876,14.435 7.161,21.7c0.566,1.799 1.157,3.648 1.228,5.543c-0.527,3.023 -2.755,5.323 -4.274,7.885c-1.198,2.019 -2.354,4.236 -4.251,5.633c-0.635,0.468 -1.429,-0.517 -2.002,-0.931c-2.904,-2.098 -5.352,-4.752 -8.033,-7.122c-1.298,-1.147 -2.392,-2.723 -2.273,-4.527c-0.252,-4.991 0.489,-9.962 0.814,-14.935c0.247,-3.761 0.564,-7.517 0.593,-11.286c0.017,-2.168 0.294,-4.463 1.912,-6.09c1.233,-1.241 3.045,-1.804 4.711,-1.286Z"/><path id="path10" d="M151.528,151.13c-4.499,2.422 -6.52,8.181 -5.586,13.021c0.502,2.602 3.583,2.978 5.813,3.046c1.941,0.058 4.078,-0.557 4.559,-2.689c1.254,-5.56 -0.872,-10.645 -4.786,-13.378Zm-0.135,-10.877c5.967,-0.866 12.309,0.095 17.472,3.322c4.482,2.802 7.871,7.466 8.557,12.786c1.036,8.038 -1.784,16.585 -7.578,22.26c-4.904,4.803 -12.117,6.715 -18.883,5.665c-6.77,-1.051 -13.52,-4.483 -16.857,-10.666c-3.479,-6.445 -2.568,-14.395 0.515,-20.779c2.878,-5.958 8.212,-11.169 14.881,-12.447c0.626,-0.098 1.26,-0.145 1.893,-0.141Z"/></svg><
\ No newline at end of file