internal/packing: allow initialization with a rectangle size

Updates #2327
This commit is contained in:
Hajime Hoshi 2023-02-23 00:44:56 +09:00
parent b08b740914
commit 0720ec2251
3 changed files with 30 additions and 20 deletions

View File

@ -684,12 +684,19 @@ func (i *Image) allocate(putOnAtlas bool) {
return return
} }
} }
size := minSize
for i.width+2*i.paddingSize() > size || i.height+2*i.paddingSize() > size { width, height := minSize, minSize
if size == maxSize { for i.width+2*i.paddingSize() > width {
if width == maxSize {
panic(fmt.Sprintf("atlas: the image being put on an atlas is too big: width: %d, height: %d", i.width, i.height)) panic(fmt.Sprintf("atlas: the image being put on an atlas is too big: width: %d, height: %d", i.width, i.height))
} }
size *= 2 width *= 2
}
for i.height+2*i.paddingSize() > height {
if height == maxSize {
panic(fmt.Sprintf("atlas: the image being put on an atlas is too big: width: %d, height: %d", i.width, i.height))
}
height *= 2
} }
typ := restorable.ImageTypeRegular typ := restorable.ImageTypeRegular
@ -697,8 +704,8 @@ func (i *Image) allocate(putOnAtlas bool) {
typ = restorable.ImageTypeVolatile typ = restorable.ImageTypeVolatile
} }
b := &backend{ b := &backend{
restorable: restorable.NewImage(size, size, typ), restorable: restorable.NewImage(width, height, typ),
page: packing.NewPage(size, maxSize), page: packing.NewPage(width, height, maxSize),
} }
theBackends = append(theBackends, b) theBackends = append(theBackends, b)

View File

@ -44,16 +44,19 @@ func isPositivePowerOf2(x int) bool {
return true return true
} }
func NewPage(initSize int, maxSize int) *Page { func NewPage(initWidth, initHeight int, maxSize int) *Page {
if !isPositivePowerOf2(initSize) { if !isPositivePowerOf2(initWidth) {
panic(fmt.Sprintf("packing: initSize must be a positive power of 2 but %d", initSize)) panic(fmt.Sprintf("packing: initWidth must be a positive power of 2 but %d", initWidth))
}
if !isPositivePowerOf2(initHeight) {
panic(fmt.Sprintf("packing: initHeight must be a positive power of 2 but %d", initHeight))
} }
if !isPositivePowerOf2(maxSize) { if !isPositivePowerOf2(maxSize) {
panic(fmt.Sprintf("packing: maxSize must be a positive power of 2 but %d", maxSize)) panic(fmt.Sprintf("packing: maxSize must be a positive power of 2 but %d", maxSize))
} }
return &Page{ return &Page{
width: initSize, width: initWidth,
height: initSize, height: initHeight,
maxSize: maxSize, maxSize: maxSize,
} }
} }

View File

@ -211,7 +211,7 @@ func TestPage(t *testing.T) {
} }
for _, c := range cases { for _, c := range cases {
p := packing.NewPage(1024, 1024) p := packing.NewPage(1024, 1024, 1024)
nodes := []*packing.Node{} nodes := []*packing.Node{}
nnodes := 0 nnodes := 0
for i, in := range c.In { for i, in := range c.In {
@ -254,7 +254,7 @@ func TestPage(t *testing.T) {
} }
func TestAlloc(t *testing.T) { func TestAlloc(t *testing.T) {
p := packing.NewPage(1024, 2048) p := packing.NewPage(1024, 1024, 2048)
w, h := p.Size() w, h := p.Size()
p.Alloc(w/2, h/2) p.Alloc(w/2, h/2)
@ -277,7 +277,7 @@ func TestAlloc(t *testing.T) {
} }
func TestAlloc2(t *testing.T) { func TestAlloc2(t *testing.T) {
p := packing.NewPage(1024, 2048) p := packing.NewPage(1024, 1024, 2048)
w, h := p.Size() w, h := p.Size()
p.Alloc(w/2, h/2) p.Alloc(w/2, h/2)
n1 := p.Alloc(w/2, h/2) n1 := p.Alloc(w/2, h/2)
@ -299,7 +299,7 @@ func TestAlloc2(t *testing.T) {
} }
func TestAllocJustSize(t *testing.T) { func TestAllocJustSize(t *testing.T) {
p := packing.NewPage(1024, 4096) p := packing.NewPage(1024, 1024, 4096)
if p.Alloc(4096, 4096) == nil { if p.Alloc(4096, 4096) == nil {
t.Errorf("got: nil, want: non-nil") t.Errorf("got: nil, want: non-nil")
} }
@ -307,7 +307,7 @@ func TestAllocJustSize(t *testing.T) {
// Issue #1454 // Issue #1454
func TestAllocTooMuch(t *testing.T) { func TestAllocTooMuch(t *testing.T) {
p := packing.NewPage(1024, 4096) p := packing.NewPage(1024, 1024, 4096)
p.Alloc(1, 1) p.Alloc(1, 1)
if p.Alloc(4096, 4096) != nil { if p.Alloc(4096, 4096) != nil {
t.Errorf("got: non-nil, want: nil") t.Errorf("got: non-nil, want: nil")
@ -315,7 +315,7 @@ func TestAllocTooMuch(t *testing.T) {
} }
func TestNonSquareAlloc(t *testing.T) { func TestNonSquareAlloc(t *testing.T) {
p := packing.NewPage(1024, 16384) p := packing.NewPage(1024, 1024, 16384)
n0 := p.Alloc(16384, 1) n0 := p.Alloc(16384, 1)
if _, h := p.Size(); h != 1024 { if _, h := p.Size(); h != 1024 {
t.Errorf("got: %d, want: 1024", h) t.Errorf("got: %d, want: 1024", h)
@ -329,7 +329,7 @@ func TestNonSquareAlloc(t *testing.T) {
} }
func TestExtend(t *testing.T) { func TestExtend(t *testing.T) {
p := packing.NewPage(1024, 2048) p := packing.NewPage(1024, 1024, 2048)
n0 := p.Alloc(1024, 1024) n0 := p.Alloc(1024, 1024)
if n0 == nil { if n0 == nil {
t.Errorf("p.Alloc(1024, 1024) failed") t.Errorf("p.Alloc(1024, 1024) failed")
@ -365,7 +365,7 @@ func TestExtend(t *testing.T) {
} }
func TestExtend2(t *testing.T) { func TestExtend2(t *testing.T) {
p := packing.NewPage(1024, 2048) p := packing.NewPage(1024, 1024, 2048)
n0 := p.Alloc(1024, 1024) n0 := p.Alloc(1024, 1024)
if n0 == nil { if n0 == nil {
t.Errorf("p.Alloc(1024, 1024) failed") t.Errorf("p.Alloc(1024, 1024) failed")
@ -397,7 +397,7 @@ func TestExtend2(t *testing.T) {
} }
func TestExtend3(t *testing.T) { func TestExtend3(t *testing.T) {
p := packing.NewPage(1024, 2048) p := packing.NewPage(1024, 1024, 2048)
// Allocate a small area that doesn't touch the left edge and the bottom edge. // Allocate a small area that doesn't touch the left edge and the bottom edge.
// Allocating (1, 1) would split the entire region into left and right in the current implementation, // Allocating (1, 1) would split the entire region into left and right in the current implementation,