The power-of-two dimension restriction on textures really cuts down the size of the search space, so it might be feasible to simply try progressively bigger textures until you find one that fits.
For instance, here’s how I’m finding a minimal texture to pack a font into (the glyphs have been sorted for size previously)
private Dimension calculateTextureSize()
{
// mean glyph size
float mean = 0;
for( Glyph g : glyphs )
{
mean += g.image.getWidth();
mean += g.image.getHeight();
}
mean /= glyphs.size() * 2;
// initial guess
int dim = GLUtil.nextPowerOf2( ( int ) ( mean * Math.sqrt( glyphs.size() ) ) ) / 2;
dim = Math.max( 2, dim );
Dimension d = new Dimension( dim / 2, dim );
boolean growWidth = true;
boolean success = false;
do
{
// alternate expanding horizontally and vertically
if( growWidth )
{
d.setWidth( d.getWidth() * 2 );
}
else
{
d.setHeight( d.getHeight() * 2 );
}
growWidth = !growWidth;
RectanglePacker<Glyph> packer = new RectanglePacker<Glyph>( d.getWidth(), d.getHeight() );
Iterator<Glyph> iter = glyphs.iterator();
boolean fit = true;
while( fit && iter.hasNext() )
{
Glyph g = iter.next();
fit &= packer.insert( g.image.getWidth(), g.image.getHeight(), g ) != null;
}
success = fit;
}
while( !success );
return d;
}
See this post for an example of the packed texture.