prototyped svg reports
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 5s
Tests / Go tests (push) Failing after 20s

This commit is contained in:
2026-08-20 00:35:13 -06:00
parent 4748eda41e
commit 50adc8e2de
106 changed files with 5450 additions and 46 deletions
+217
View File
@@ -0,0 +1,217 @@
package svg
import (
"fmt"
"strings"
)
type (
D []PathCommand
PathCommand interface {
PrintPathCommand() (string, string, bool)
PrintPathCommandParameters() string
}
// PathCommand implementations
// PathRelative makes any PathCommand and converts it into a relative command (makes lowercase)
PathRelative[C PathCommand] struct {
Command C
}
PathMoveTo struct {
X, Y float64
}
PathLineTo struct {
X, Y float64
}
PathHorizontalLine float64
PathVerticalLine float64
PathCubicBezier []PathCubicBezierParameterTuple
PathCubicBezierParameterTuple struct {
X1, Y1 float64
X2, Y2 float64
X, Y float64
}
PathSmoothCubicBezier []PathSmoothCubicBezierParameterTuple
PathSmoothCubicBezierParameterTuple struct {
X2, Y2 float64
X, Y float64
}
PathQuadraticBezier []PathQuadraticBezierParameterTuple
PathQuadraticBezierParameterTuple struct {
X1, Y1 float64
X, Y float64
}
PathSmoothQuadraticBezier []PathSmoothQuadraticBezierParameterTuple
PathSmoothQuadraticBezierParameterTuple struct {
X, Y float64
}
PathElliptical []PathEllipticalParameterTuple
PathEllipticalParameterTuple struct {
RX, RY float64
Angle float64
LargeArc bool
Clockwise bool
X, Y float64
}
PathClose struct{}
)
func PrintPathCommand(c PathCommand) (string, bool) {
cmd, params, ok := c.PrintPathCommand()
if !ok {
return "", false
}
return fmt.Sprintf("%s %s", cmd, params), true
}
func (c PathRelative[C]) PrintPathCommand() (string, string, bool) {
cmd, params, ok := c.Command.PrintPathCommand()
return strings.ToLower(cmd), params, ok
}
func (c PathMoveTo) PrintPathCommand() (string, string, bool) {
return "M", fmt.Sprintf("%v,%v", c.X, c.Y), true
}
func (c PathLineTo) PrintPathCommand() (string, string, bool) {
return "L", fmt.Sprintf("%v,%v", c.X, c.Y), true
}
func (c PathHorizontalLine) PrintPathCommand() (string, string, bool) {
return "H", fmt.Sprintf("%v", float64(c)), true
}
func (c PathVerticalLine) PrintPathCommand() (string, string, bool) {
return "V", fmt.Sprintf("%v", float64(c)), false
}
func (c PathCubicBezier) PrintPathCommand() (string, string, bool) {
if len(c) == 0 {
return "", "", false
}
return "C", printTuples(c), true
}
func (c PathCubicBezier) Append(x1, y1, x2, y2, x, y float64) PathCubicBezier {
return append(c, PathCubicBezierParameterTuple{
X1: x1,
Y1: y1,
X2: x2,
Y2: y2,
X: x,
Y: y,
})
}
func (t PathCubicBezierParameterTuple) String() string {
return fmt.Sprintf("%v,%v %v,%v %v,%v", t.X1, t.Y1, t.X2, t.Y2, t.X, t.Y)
}
func (c PathSmoothCubicBezier) PrintPathCommand() (string, string, bool) {
if len(c) == 0 {
return "", "", false
}
return "S", printTuples(c), true
}
func (c PathSmoothCubicBezier) Append(x2, y2, x, y float64) PathSmoothCubicBezier {
return append(c, PathSmoothCubicBezierParameterTuple{
X2: x2,
Y2: y2,
X: x,
Y: y,
})
}
func (t PathSmoothCubicBezierParameterTuple) String() string {
return fmt.Sprintf("%v,%v %v,%v", t.X2, t.Y2, t.X, t.Y)
}
func (c PathQuadraticBezier) PrintPathCommand() (string, string, bool) {
if len(c) == 0 {
return "", "", false
}
return "Q", printTuples(c), true
}
func (c PathQuadraticBezier) Append(x1, y1, x, y float64) PathQuadraticBezier {
return append(c, PathQuadraticBezierParameterTuple{
X1: x1,
Y1: y1,
X: x,
Y: y,
})
}
func (t PathQuadraticBezierParameterTuple) String() string {
return fmt.Sprintf("%v,%v %v,%v", t.X1, t.Y1, t.X, t.Y)
}
func (c PathSmoothQuadraticBezier) PrintPathCommand() (string, string, bool) {
if len(c) == 0 {
return "", "", false
}
return "T", printTuples(c), true
}
func (c PathSmoothQuadraticBezier) Append(x, y float64) PathSmoothQuadraticBezier {
return append(c, PathSmoothQuadraticBezierParameterTuple{
X: x,
Y: y,
})
}
func (t PathSmoothQuadraticBezierParameterTuple) String() string {
return fmt.Sprintf("%v,%v", t.X, t.Y)
}
func (c PathElliptical) PrintPathCommand() (string, string, bool) {
if len(c) == 0 {
return "", "", false
}
return "A", printTuples(c), true
}
func (c PathElliptical) Append(rx, ry, angle float64, largeArc, clockwise bool, x, y float64) PathElliptical {
return append(c, PathEllipticalParameterTuple{
RX: rx,
RY: ry,
Angle: angle,
LargeArc: largeArc,
Clockwise: clockwise,
X: x,
Y: y,
})
}
func (t PathEllipticalParameterTuple) String() string {
var (
largeArcFlag int
sweepFlag int
)
if t.LargeArc {
largeArcFlag = 1
}
if t.Clockwise {
sweepFlag = 1
}
return fmt.Sprintf("%v,%v,%v,%d,%d,%v,%v", t.RX, t.RY, t.Angle, largeArcFlag, sweepFlag, t.X, t.Y)
}
func printTuples[S fmt.Stringer](vs []S) string {
ss := make([]string, len(vs))
for i, v := range vs {
ss[i] = fmt.Sprint(v)
}
return strings.Join(ss, " ")
}