// Package svg draws the small on-chain SVGs of GnoRadio (covers, tickets,
// charts) with a strings.Builder, which keeps vm/qrender gas low.
package svg
import (
"encoding/base64"
"strconv"
"strings"
"gno.land/p/nt/markdown/sanitize/v0"
)
type Canvas struct{ b strings.Builder }
// New opens a w×h SVG whose `)
return c
}
func (c *Canvas) Raw(s string) { c.b.WriteString(s) }
// Rect draws a rectangle; extra holds more attributes, e.g. ` mask="url(#h)"`.
func (c *Canvas) Rect(x, y, w, h, rx int, fill, extra string) {
c.b.WriteString(``)
}
func (c *Canvas) Circle(cx, cy, r int, fill string) {
c.b.WriteString(``)
}
// Text writes s escaped; attrs follows font-size, e.g. ` text-anchor="end" class="m"`.
func (c *Canvas) Text(x, y int, s, fill string, size int, attrs string) {
c.b.WriteString(`` + Escape(s) + ``)
}
// Data closes the SVG and returns it as a base64 data URI.
func (c *Canvas) Data() string {
c.b.WriteString("")
return "data:image/svg+xml;base64," + base64.StdEncoding.EncodeToString([]byte(c.b.String()))
}
// Image closes the SVG and returns it as a markdown image.
func (c *Canvas) Image(alt string) string {
return " + ")"
}
// Escape makes text safe inside SVG: titles and names may hold '&'.
func Escape(s string) string {
s = strings.ReplaceAll(s, "&", "&")
s = strings.ReplaceAll(s, "<", "<")
return strings.ReplaceAll(s, ">", ">")
}
// Clip shortens s to n runes, ending with an ellipsis.
func Clip(s string, n int) string {
r := []rune(s)
if len(r) <= n {
return s
}
return string(r[:n-1]) + "…"
}
// FNV is the 32-bit FNV-1a hash, used to pick a composition from a title.
func FNV(s string) uint32 {
h := uint32(2166136261)
for i := 0; i < len(s); i++ {
h ^= uint32(s[i])
h *= 16777619
}
return h
}
func itoa(n int) string { return strconv.Itoa(n) }