package svg import ( "fmt" "strings" ) // TODO consider replacing the Transform matrices with a single 'matrix' type with different constructors and a builder/chaining api. type ( Transform []TransformExpression // Transform is itself a Transform, meaning you could nest them, if you wanted. TransformExpression interface { PrintTransform() string } // TransformExpression implementations // They can tehemselves be used as standalone 'transform' attributes. TransformRotate float64 TransformRotateAbout struct { A float64 X, Y float64 } TransformTranslate struct { X, Y float64 } TransformSkewX float64 TransformSkewY float64 TransformScale struct { X, Y float64 } ) func (Transform) PrintKey() string { return "transform" } func (ts Transform) PrintValue() (string, bool) { return fmt.Sprintf("%q", ts.PrintTransform()), true } func (ts Transform) PrintTransform() string { ss := make([]string, len(ts)) for i, t := range ts { ss[i] = t.PrintTransform() } return strings.Join(ss, " ") } func (ts Transform) Rotate(a float64) Transform { return append(ts, TransformRotate(a)) } func (ts Transform) RotateAbout(a, x, y float64) Transform { return append(ts, TransformRotateAbout{A: a, X: x, Y: y}) } func (ts Transform) Translate(x, y float64) Transform { return append(ts, TransformTranslate{X: x, Y: y}) } func (ts Transform) SkewX(x float64) Transform { return append(ts, TransformSkewX(x)) } func (ts Transform) SkewY(y float64) Transform { return append(ts, TransformSkewY(y)) } func (ts Transform) Scale(x, y float64) Transform { return append(ts, TransformScale{X: x, Y: y}) } func (TransformRotate) PrintKey() string { return "transform" } func (t TransformRotate) PrintValue() (string, bool) { return fmt.Sprintf("%q", t.PrintTransform()), true } func (t TransformRotate) PrintTransform() string { return fmt.Sprintf("rotate(%v)", float64(t)) } func (t TransformRotate) About(x, y float64) TransformRotateAbout { return TransformRotateAbout{ A: float64(t), X: x, Y: y, } } func (TransformRotateAbout) PrintKey() string { return "transform" } func (t TransformRotateAbout) PrintValue() (string, bool) { return fmt.Sprintf("%q", t.PrintTransform()), true } func (t TransformRotateAbout) PrintTransform() string { return fmt.Sprintf("rotate(%v %v %v)", t.A, t.X, t.Y) } func (TransformTranslate) PrintKey() string { return "transform" } func (t TransformTranslate) PrintValue() (string, bool) { return fmt.Sprintf("%q", t.PrintTransform()), true } func (t TransformTranslate) PrintTransform() string { return fmt.Sprintf("translate(%v %v)", t.X, t.Y) } func (TransformSkewX) PrintKey() string { return "transform" } func (t TransformSkewX) PrintValue() (string, bool) { return fmt.Sprintf("%q", t.PrintTransform()), true } func (t TransformSkewX) PrintTransform() string { return fmt.Sprintf("skewX(%v)", float64(t)) } func (TransformSkewY) PrintKey() string { return "transform" } func (t TransformSkewY) PrintValue() (string, bool) { return fmt.Sprintf("%q", t.PrintTransform()), true } func (t TransformSkewY) PrintTransform() string { return fmt.Sprintf("skewY(%v)", float64(t)) } func (TransformScale) PrintKey() string { return "transform" } func (t TransformScale) PrintValue() (string, bool) { return fmt.Sprintf("%q", t.PrintTransform()), true } func (t TransformScale) PrintTransform() string { return fmt.Sprintf("scale(%v %v)", t.X, t.Y) }