diff options
Diffstat (limited to 'vendor/gioui.org/gpu/pack.go')
-rw-r--r-- | vendor/gioui.org/gpu/pack.go | 86 |
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 } |