aboutsummaryrefslogtreecommitdiff
path: root/vendor/gioui.org/gpu/pack.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gioui.org/gpu/pack.go')
-rw-r--r--vendor/gioui.org/gpu/pack.go86
1 files changed, 53 insertions, 33 deletions
diff --git a/vendor/gioui.org/gpu/pack.go b/vendor/gioui.org/gpu/pack.go
index c4dbaad..3f8c925 100644
--- a/vendor/gioui.org/gpu/pack.go
+++ b/vendor/gioui.org/gpu/pack.go
@@ -9,8 +9,8 @@ import (
// packer packs a set of many smaller rectangles into
// much fewer larger atlases.
type packer struct {
- maxDim int
- spaces []image.Rectangle
+ maxDims image.Point
+ spaces []image.Rectangle
sizes []image.Point
pos image.Point
@@ -41,45 +41,65 @@ func (p *packer) newPage() {
p.sizes = append(p.sizes, image.Point{})
p.spaces = p.spaces[:0]
p.spaces = append(p.spaces, image.Rectangle{
- Max: image.Point{X: p.maxDim, Y: p.maxDim},
+ Max: image.Point{X: 1e6, Y: 1e6},
})
}
func (p *packer) tryAdd(s image.Point) (placement, bool) {
- // Go backwards to prioritize smaller spaces first.
- for i := len(p.spaces) - 1; i >= 0; i-- {
- space := p.spaces[i]
+ var (
+ bestIdx = -1
+ bestSpace image.Rectangle
+ bestSize = p.maxDims
+ )
+ // Go backwards to prioritize smaller spaces.
+ for i, space := range p.spaces {
rightSpace := space.Dx() - s.X
bottomSpace := space.Dy() - s.Y
- if rightSpace >= 0 && bottomSpace >= 0 {
- // Remove space.
- p.spaces[i] = p.spaces[len(p.spaces)-1]
- p.spaces = p.spaces[:len(p.spaces)-1]
- // Put s in the top left corner and add the (at most)
- // two smaller spaces.
- pos := space.Min
- if bottomSpace > 0 {
- p.spaces = append(p.spaces, image.Rectangle{
- Min: image.Point{X: pos.X, Y: pos.Y + s.Y},
- Max: image.Point{X: space.Max.X, Y: space.Max.Y},
- })
- }
- if rightSpace > 0 {
- p.spaces = append(p.spaces, image.Rectangle{
- Min: image.Point{X: pos.X + s.X, Y: pos.Y},
- Max: image.Point{X: space.Max.X, Y: pos.Y + s.Y},
- })
- }
- idx := len(p.sizes) - 1
- size := &p.sizes[idx]
- if x := pos.X + s.X; x > size.X {
- size.X = x
+ if rightSpace < 0 || bottomSpace < 0 {
+ continue
+ }
+ idx := len(p.sizes) - 1
+ size := p.sizes[idx]
+ if x := space.Min.X + s.X; x > size.X {
+ if x > p.maxDims.X {
+ continue
}
- if y := pos.Y + s.Y; y > size.Y {
- size.Y = y
+ size.X = x
+ }
+ if y := space.Min.Y + s.Y; y > size.Y {
+ if y > p.maxDims.Y {
+ continue
}
- return placement{Idx: idx, Pos: pos}, true
+ size.Y = y
}
+ if size.X*size.Y < bestSize.X*bestSize.Y {
+ bestIdx = i
+ bestSpace = space
+ bestSize = size
+ }
+ }
+ if bestIdx == -1 {
+ return placement{}, false
+ }
+ // Remove space.
+ p.spaces[bestIdx] = p.spaces[len(p.spaces)-1]
+ p.spaces = p.spaces[:len(p.spaces)-1]
+ // Put s in the top left corner and add the (at most)
+ // two smaller spaces.
+ pos := bestSpace.Min
+ if rem := bestSpace.Dy() - s.Y; rem > 0 {
+ p.spaces = append(p.spaces, image.Rectangle{
+ Min: image.Point{X: pos.X, Y: pos.Y + s.Y},
+ Max: image.Point{X: bestSpace.Max.X, Y: bestSpace.Max.Y},
+ })
+ }
+ if rem := bestSpace.Dx() - s.X; rem > 0 {
+ p.spaces = append(p.spaces, image.Rectangle{
+ Min: image.Point{X: pos.X + s.X, Y: pos.Y},
+ Max: image.Point{X: bestSpace.Max.X, Y: pos.Y + s.Y},
+ })
}
- return placement{}, false
+ idx := len(p.sizes) - 1
+ p.sizes[idx] = bestSize
+ return placement{Idx: idx, Pos: pos}, true
}