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
}
}
size := minSize
for i.width+2*i.paddingSize() > size || i.height+2*i.paddingSize() > size {
if size == maxSize {
width, height := minSize, minSize
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))
}
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
@ -697,8 +704,8 @@ func (i *Image) allocate(putOnAtlas bool) {
typ = restorable.ImageTypeVolatile
}
b := &backend{
restorable: restorable.NewImage(size, size, typ),
page: packing.NewPage(size, maxSize),
restorable: restorable.NewImage(width, height, typ),
page: packing.NewPage(width, height, maxSize),
}
theBackends = append(theBackends, b)

View File

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

View File

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