themes and styles
This commit is contained in:
@@ -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()
|
||||
}
|
||||
Reference in New Issue
Block a user