136 lines
4.1 KiB
Go
136 lines
4.1 KiB
Go
package engine
|
|
|
|
// Grid represents a 4x4 layout grid for positioning shapes in a jdenticon
|
|
type Grid struct {
|
|
Size float64
|
|
Cell int
|
|
X int
|
|
Y int
|
|
Padding int
|
|
}
|
|
|
|
// Position represents an x, y coordinate pair
|
|
type Position struct {
|
|
X, Y int
|
|
}
|
|
|
|
// NewGrid creates a new Grid with the specified icon size and padding ratio
|
|
func NewGrid(iconSize float64, paddingRatio float64) *Grid {
|
|
// Calculate padding and round to nearest integer (matches JS: (0.5 + size * parsedConfig.iconPadding) | 0)
|
|
padding := int(0.5 + iconSize*paddingRatio)
|
|
size := iconSize - float64(padding*2)
|
|
|
|
// Calculate cell size and ensure it is an integer (matches JS: 0 | (size / 4))
|
|
cell := int(size / 4)
|
|
|
|
// Center the icon since cell size is integer-based (matches JS implementation)
|
|
// Since the cell size is integer based, the actual icon will be slightly smaller than specified => center icon
|
|
x := padding + int((size - float64(cell*4))/2)
|
|
y := padding + int((size - float64(cell*4))/2)
|
|
|
|
return &Grid{
|
|
Size: size,
|
|
Cell: cell,
|
|
X: x,
|
|
Y: y,
|
|
Padding: padding,
|
|
}
|
|
}
|
|
|
|
// CellToCoordinate converts a grid cell position to actual coordinates
|
|
func (g *Grid) CellToCoordinate(cellX, cellY int) (x, y float64) {
|
|
return float64(g.X + cellX*g.Cell), float64(g.Y + cellY*g.Cell)
|
|
}
|
|
|
|
// GetCellSize returns the size of each cell in the grid
|
|
func (g *Grid) GetCellSize() float64 {
|
|
return float64(g.Cell)
|
|
}
|
|
|
|
// LayoutEngine manages the overall layout and positioning of icon elements
|
|
type LayoutEngine struct {
|
|
grid *Grid
|
|
}
|
|
|
|
// NewLayoutEngine creates a new LayoutEngine with the specified parameters
|
|
func NewLayoutEngine(iconSize float64, paddingRatio float64) *LayoutEngine {
|
|
return &LayoutEngine{
|
|
grid: NewGrid(iconSize, paddingRatio),
|
|
}
|
|
}
|
|
|
|
// Grid returns the underlying grid
|
|
func (le *LayoutEngine) Grid() *Grid {
|
|
return le.grid
|
|
}
|
|
|
|
// GetShapePositions returns the positions for different shape types based on the jdenticon pattern
|
|
func (le *LayoutEngine) GetShapePositions(shapeType string) []Position {
|
|
switch shapeType {
|
|
case "sides":
|
|
// Sides: positions around the perimeter (8 positions)
|
|
return []Position{
|
|
{1, 0}, {2, 0}, {2, 3}, {1, 3}, // top and bottom
|
|
{0, 1}, {3, 1}, {3, 2}, {0, 2}, // left and right
|
|
}
|
|
case "corners":
|
|
// Corners: four corner positions
|
|
return []Position{
|
|
{0, 0}, {3, 0}, {3, 3}, {0, 3},
|
|
}
|
|
case "center":
|
|
// Center: four center positions
|
|
return []Position{
|
|
{1, 1}, {2, 1}, {2, 2}, {1, 2},
|
|
}
|
|
default:
|
|
return []Position{}
|
|
}
|
|
}
|
|
|
|
// ApplySymmetry applies symmetrical transformations to position indices
|
|
// This ensures the icon has the characteristic jdenticon symmetry
|
|
func ApplySymmetry(positions []Position, index int) []Position {
|
|
if index >= len(positions) {
|
|
return positions
|
|
}
|
|
|
|
// For jdenticon, we apply rotational symmetry
|
|
// The pattern is designed to be symmetrical, so we don't need to modify positions
|
|
// The symmetry is achieved through the predefined position arrays
|
|
return positions
|
|
}
|
|
|
|
// GetTransformedPosition applies rotation and returns the final position
|
|
func (le *LayoutEngine) GetTransformedPosition(cellX, cellY int, rotation int) (x, y float64, cellSize float64) {
|
|
// Apply rotation if needed (rotation is 0-3 for 0°, 90°, 180°, 270°)
|
|
switch rotation % 4 {
|
|
case 0: // 0°
|
|
// No rotation
|
|
case 1: // 90° clockwise
|
|
cellX, cellY = cellY, 3-cellX
|
|
case 2: // 180°
|
|
cellX, cellY = 3-cellX, 3-cellY
|
|
case 3: // 270° clockwise (90° counter-clockwise)
|
|
cellX, cellY = 3-cellY, cellX
|
|
}
|
|
|
|
x, y = le.grid.CellToCoordinate(cellX, cellY)
|
|
cellSize = le.grid.GetCellSize()
|
|
return
|
|
}
|
|
|
|
// ValidateGrid checks if the grid configuration is valid
|
|
func (g *Grid) ValidateGrid() bool {
|
|
return g.Cell > 0 && g.Size > 0 && g.Padding >= 0
|
|
}
|
|
|
|
// GetIconBounds returns the bounds of the icon within the grid
|
|
func (g *Grid) GetIconBounds() (x, y, width, height float64) {
|
|
return float64(g.X), float64(g.Y), float64(g.Cell * 4), float64(g.Cell * 4)
|
|
}
|
|
|
|
// GetCenterOffset returns the offset needed to center content within a cell
|
|
func (g *Grid) GetCenterOffset() (dx, dy float64) {
|
|
return float64(g.Cell) / 2, float64(g.Cell) / 2
|
|
} |