slightly more rigorous bounds checking and auto-fit
This commit is contained in:
parent
bba75e5d4c
commit
28f01842de
13 changed files with 475 additions and 195 deletions
172
box.go
172
box.go
|
|
@ -8,9 +8,6 @@ type Box struct {
|
|||
Left int
|
||||
Right int
|
||||
Bottom int
|
||||
|
||||
Height int
|
||||
Width int
|
||||
}
|
||||
|
||||
// IsZero returns if the box is set or not.
|
||||
|
|
@ -66,3 +63,172 @@ func (b Box) GetBottom(defaults ...int) int {
|
|||
}
|
||||
return b.Bottom
|
||||
}
|
||||
|
||||
// Width returns the width
|
||||
func (b Box) Width() int {
|
||||
return AbsInt(b.Right - b.Left)
|
||||
}
|
||||
|
||||
// Height returns the height
|
||||
func (b Box) Height() int {
|
||||
return AbsInt(b.Bottom - b.Top)
|
||||
}
|
||||
|
||||
// Center returns the center of the box
|
||||
func (b Box) Center() (x, y int) {
|
||||
w, h := b.Width(), b.Height()
|
||||
return b.Left + w>>1, b.Top + h>>1
|
||||
}
|
||||
|
||||
// Aspect returns the aspect ratio of the box.
|
||||
func (b Box) Aspect() float64 {
|
||||
return float64(b.Width()) / float64(b.Height())
|
||||
}
|
||||
|
||||
// Clone returns a new copy of the box.
|
||||
func (b Box) Clone() Box {
|
||||
return Box{
|
||||
Top: b.Top,
|
||||
Left: b.Left,
|
||||
Right: b.Right,
|
||||
Bottom: b.Bottom,
|
||||
}
|
||||
}
|
||||
|
||||
// IsBiggerThan returns if a box is bigger than another box.
|
||||
func (b Box) IsBiggerThan(other Box) bool {
|
||||
return b.Top < other.Top ||
|
||||
b.Bottom > other.Bottom ||
|
||||
b.Left < other.Left ||
|
||||
b.Right > other.Right
|
||||
}
|
||||
|
||||
// IsSmallerThan returns if a box is smaller than another box.
|
||||
func (b Box) IsSmallerThan(other Box) bool {
|
||||
return b.Top > other.Top &&
|
||||
b.Bottom < other.Bottom &&
|
||||
b.Left > other.Left &&
|
||||
b.Right < other.Right
|
||||
}
|
||||
|
||||
// Equals returns if the box equals another box.
|
||||
func (b Box) Equals(other Box) bool {
|
||||
return b.Top == other.Top &&
|
||||
b.Left == other.Left &&
|
||||
b.Right == other.Right &&
|
||||
b.Bottom == other.Bottom
|
||||
}
|
||||
|
||||
// Grow grows a box based on another box.
|
||||
func (b Box) Grow(other Box) Box {
|
||||
return Box{
|
||||
Top: MinInt(b.Top, other.Top),
|
||||
Left: MinInt(b.Left, other.Left),
|
||||
Right: MaxInt(b.Right, other.Right),
|
||||
Bottom: MaxInt(b.Bottom, other.Bottom),
|
||||
}
|
||||
}
|
||||
|
||||
// Shift pushes a box by x,y.
|
||||
func (b Box) Shift(x, y int) Box {
|
||||
return Box{
|
||||
Top: b.Top + y,
|
||||
Left: b.Left + x,
|
||||
Right: b.Right + x,
|
||||
Bottom: b.Bottom + y,
|
||||
}
|
||||
}
|
||||
|
||||
// Fit is functionally the inverse of grow.
|
||||
// Fit maintains the original aspect ratio of the `other` box,
|
||||
// but constrains it to the bounds of the target box.
|
||||
func (b Box) Fit(other Box) Box {
|
||||
ba := b.Aspect()
|
||||
oa := other.Aspect()
|
||||
|
||||
if oa == ba {
|
||||
return b.Clone()
|
||||
}
|
||||
|
||||
bw, bh := float64(b.Width()), float64(b.Height())
|
||||
bw2 := int(bw) >> 1
|
||||
bh2 := int(bh) >> 1
|
||||
if oa > ba { // ex. 16:9 vs. 4:3
|
||||
var noh2 int
|
||||
if oa > 1.0 {
|
||||
noh2 = int(bw/oa) >> 1
|
||||
} else {
|
||||
noh2 = int(bh*oa) >> 1
|
||||
}
|
||||
return Box{
|
||||
Top: (b.Top + bh2) - noh2,
|
||||
Left: b.Left,
|
||||
Right: b.Right,
|
||||
Bottom: (b.Top + bh2) + noh2,
|
||||
}
|
||||
}
|
||||
var now2 int
|
||||
if oa > 1.0 {
|
||||
now2 = int(bh/oa) >> 1
|
||||
} else {
|
||||
now2 = int(bw*oa) >> 1
|
||||
}
|
||||
return Box{
|
||||
Top: b.Top,
|
||||
Left: (b.Left + bw2) - now2,
|
||||
Right: (b.Left + bw2) + now2,
|
||||
Bottom: b.Bottom,
|
||||
}
|
||||
}
|
||||
|
||||
// Constrain is similar to `Fit` except that it will work
|
||||
// more literally like the opposite of grow.
|
||||
func (b Box) Constrain(other Box) Box {
|
||||
newBox := b.Clone()
|
||||
if other.Top < b.Top {
|
||||
delta := b.Top - other.Top
|
||||
newBox.Top = other.Top + delta
|
||||
}
|
||||
|
||||
if other.Left < b.Left {
|
||||
delta := b.Left - other.Left
|
||||
newBox.Left = other.Left + delta
|
||||
}
|
||||
|
||||
if other.Right > b.Right {
|
||||
delta := other.Right - b.Right
|
||||
newBox.Right = other.Right - delta
|
||||
}
|
||||
|
||||
if other.Bottom > b.Bottom {
|
||||
delta := other.Bottom - b.Bottom
|
||||
newBox.Bottom = other.Bottom - delta
|
||||
}
|
||||
return newBox
|
||||
}
|
||||
|
||||
// OuterConstrain is similar to `Constraint` with the difference
|
||||
// that it applies corrections
|
||||
func (b Box) OuterConstrain(bounds, other Box) Box {
|
||||
newBox := b.Clone()
|
||||
if other.Top < bounds.Top {
|
||||
delta := bounds.Top - other.Top
|
||||
newBox.Top = b.Top + delta
|
||||
}
|
||||
|
||||
if other.Left < bounds.Left {
|
||||
delta := bounds.Left - other.Left
|
||||
newBox.Left = b.Left + delta
|
||||
}
|
||||
|
||||
if other.Right > bounds.Right {
|
||||
delta := other.Right - bounds.Right
|
||||
newBox.Right = b.Right - delta
|
||||
}
|
||||
|
||||
if other.Bottom > bounds.Bottom {
|
||||
delta := other.Bottom - bounds.Bottom
|
||||
newBox.Bottom = b.Bottom - delta
|
||||
}
|
||||
return newBox
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue