themes and styles

This commit is contained in:
IliaDenisov
2026-03-08 15:31:17 +02:00
parent e37a67bc99
commit 1c2fc30127
39 changed files with 2693 additions and 199 deletions
@@ -0,0 +1,96 @@
package world
import (
"hash"
"hash/fnv"
"image/color"
"math"
)
// hashU64 writes v to the hash in little-endian form.
// We keep it manual to avoid extra allocations and dependencies.
func hashU64(h hash.Hash64, v uint64) {
var b [8]byte
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
b[4] = byte(v >> 32)
b[5] = byte(v >> 40)
b[6] = byte(v >> 48)
b[7] = byte(v >> 56)
_, _ = h.Write(b[:])
}
func hashBool(h hash.Hash64, v bool) {
if v {
hashU64(h, 1)
} else {
hashU64(h, 0)
}
}
func hashColor(h hash.Hash64, c color.Color) {
if c == nil {
hashU64(h, 0)
return
}
r, g, b, a := c.RGBA()
hashU64(h, uint64(r))
hashU64(h, uint64(g))
hashU64(h, uint64(b))
hashU64(h, uint64(a))
}
// fingerprint returns a stable hash of the override content.
//
// Notes on semantics:
// - FillColor / StrokeColor: nil means "unset" (do not override). Transparent override is represented
// by a non-nil color with alpha=0.
// - Pointer fields (*float64, *[]float64) encode presence via nil/non-nil.
// - StrokeDashes: nil pointer means "unset"; non-nil pointer to nil slice means "set to nil".
func (o StyleOverride) fingerprint() uint64 {
h := fnv.New64a() // returns hash.Hash64
// FillColor / StrokeColor
hashBool(h, o.FillColor != nil)
hashColor(h, o.FillColor)
hashBool(h, o.StrokeColor != nil)
hashColor(h, o.StrokeColor)
// StrokeWidthPx
hashBool(h, o.StrokeWidthPx != nil)
if o.StrokeWidthPx != nil {
hashU64(h, math.Float64bits(*o.StrokeWidthPx))
}
// StrokeDashes
hashBool(h, o.StrokeDashes != nil)
if o.StrokeDashes != nil {
ds := *o.StrokeDashes
if ds == nil {
// Explicitly set to nil slice
hashU64(h, 0xffffffffffffffff)
} else {
hashU64(h, uint64(len(ds)))
for _, v := range ds {
hashU64(h, math.Float64bits(v))
}
}
}
// StrokeDashOffset
hashBool(h, o.StrokeDashOffset != nil)
if o.StrokeDashOffset != nil {
hashU64(h, math.Float64bits(*o.StrokeDashOffset))
}
// PointRadiusPx
hashBool(h, o.PointRadiusPx != nil)
if o.PointRadiusPx != nil {
hashU64(h, math.Float64bits(*o.PointRadiusPx))
}
return h.Sum64()
}