-
Notifications
You must be signed in to change notification settings - Fork 0
/
algorithm.go
98 lines (84 loc) · 2.18 KB
/
algorithm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package rectpack
type packAlgorithm interface {
// Reset returns the packer to its initial configured state with the specified maximum extents.
// This function will panic if width or height is less than 1.
Reset(width, height int)
// Used computes the ratio of used surface area to the maximum possible area, in the range of
// 0.0 (empty) and 1.0 (perfectly packed with no waste).
Used() float64
// Insert pushes new rectangles into packer, finding the best placement for them based on
// its configuration and current state. The padding argument specifies the amount of empty
// space that should be left between rectangles.
//
// Returns a slice of sizes that could not be packed.
Insert(padding int, sizes ...Size) []Size
// Rects returns a slice of rectangles that have been packed.
Rects() []Rect
// AllowFlip indicates if rectangles can be flipped/rotated to provide better placement.
//
// Default: false
AllowFlip(enabled bool)
// MaxSize returns the maximum size the algorithm can pack into.
MaxSize() Size
// UsedArea returns the total area that is occupied.
UsedArea() int
}
type algorithmBase struct {
packed []Rect
maxWidth int
maxHeight int
usedArea int
allowFlip bool
}
func (p *algorithmBase) Used() float64 {
return float64(p.usedArea) / float64(p.maxWidth*p.maxHeight)
}
func (p *algorithmBase) Reset(width, height int) {
p.maxWidth = width
p.maxHeight = height
p.usedArea = 0
p.packed = p.packed[:0]
}
func (p *algorithmBase) Rects() []Rect {
return p.packed
}
func (p *algorithmBase) AllowFlip(enabled bool) {
p.allowFlip = enabled
}
func (p *algorithmBase) MaxSize() Size {
return NewSize(p.maxWidth, p.maxHeight)
}
func (p *algorithmBase) UsedArea() int {
return p.usedArea
}
func abs(x int) int {
if x >= 0 {
return x
}
return -x
}
func padSize(size *Size, padding int) {
if padding <= 0 {
return
}
size.Width += padding
size.Height += padding
}
func unpadRect(rect *Rect, padding int) {
if padding <= 0 {
return
}
if rect.X == 0 {
rect.X += padding
rect.Width -= padding * 2
} else {
rect.Width -= padding
}
if rect.Y == 0 {
rect.Y += padding
rect.Height -= padding * 2
} else {
rect.Height -= padding
}
}
// vim: ts=4