Uniform grid atlas completed
This commit is contained in:
parent
0f48aaa727
commit
37d185878d
|
|
@ -7,14 +7,14 @@ namespace msdf_atlas {
|
||||||
|
|
||||||
static int floorPOT(int x) {
|
static int floorPOT(int x) {
|
||||||
int y = 1;
|
int y = 1;
|
||||||
while (x >= y)
|
while (x >= y && y<<1)
|
||||||
y <<= 1;
|
y <<= 1;
|
||||||
return y>>1;
|
return y>>1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ceilPOT(int x) {
|
static int ceilPOT(int x) {
|
||||||
int y = 1;
|
int y = 1;
|
||||||
while (x > y)
|
while (x > y && y<<1)
|
||||||
y <<= 1;
|
y <<= 1;
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
@ -103,7 +103,8 @@ GridAtlasPacker::GridAtlasPacker() :
|
||||||
miterLimit(0),
|
miterLimit(0),
|
||||||
pxAlignOriginX(false), pxAlignOriginY(false),
|
pxAlignOriginX(false), pxAlignOriginY(false),
|
||||||
scaleMaximizationTolerance(.001),
|
scaleMaximizationTolerance(.001),
|
||||||
alignedColumnsBias(.125)
|
alignedColumnsBias(.125),
|
||||||
|
cutoff(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
msdfgen::Shape::Bounds GridAtlasPacker::getMaxBounds(double &maxWidth, double &maxHeight, GlyphGeometry *glyphs, int count, double scale, double range) const {
|
msdfgen::Shape::Bounds GridAtlasPacker::getMaxBounds(double &maxWidth, double &maxHeight, GlyphGeometry *glyphs, int count, double scale, double range) const {
|
||||||
|
|
@ -176,12 +177,12 @@ double GridAtlasPacker::scaleToFit(GlyphGeometry *glyphs, int count, int cellWid
|
||||||
return minScale;
|
return minScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO tame spaghetti code
|
// Can this spaghetti code be simplified?
|
||||||
|
// Idea: Maybe it could be rewritten into a while (not all properties deduced) cycle, and compute one value in each iteration
|
||||||
int GridAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
int GridAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
||||||
if (!count)
|
if (!count)
|
||||||
return 0;
|
return 0;
|
||||||
bool cellHeightFinal = cellHeight > 0;
|
GridAtlasPacker initial(*this);
|
||||||
bool explicitRows = rows > 0;
|
|
||||||
int cellCount = 0;
|
int cellCount = 0;
|
||||||
if (columns > 0 && rows > 0)
|
if (columns > 0 && rows > 0)
|
||||||
cellCount = columns*rows;
|
cellCount = columns*rows;
|
||||||
|
|
@ -201,29 +202,23 @@ int GridAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dimensionsChanged = false;
|
if (width < 0 && cellWidth > 0 && columns > 0)
|
||||||
if (width < 0 && cellWidth > 0 && columns > 0) {
|
width = columns*cellWidth;
|
||||||
width = columns*cellWidth-padding;
|
if (height < 0 && cellHeight > 0 && rows > 0)
|
||||||
dimensionsChanged = true;
|
height = rows*cellHeight;
|
||||||
}
|
if (width != initial.width || height != initial.height)
|
||||||
if (height < 0 && cellHeight > 0 && rows > 0) {
|
|
||||||
height = rows*cellHeight-padding;
|
|
||||||
dimensionsChanged = true;
|
|
||||||
}
|
|
||||||
if (dimensionsChanged)
|
|
||||||
raiseToConstraint(width, height, dimensionsConstraint);
|
raiseToConstraint(width, height, dimensionsConstraint);
|
||||||
|
|
||||||
dimensionsChanged = false;
|
if (cellWidth < 0 && width > 0 && columns > 0)
|
||||||
if (cellWidth < 0 && width > 0 && columns > 0) {
|
|
||||||
cellWidth = (width+padding)/columns;
|
cellWidth = (width+padding)/columns;
|
||||||
dimensionsChanged = true;
|
if (cellHeight < 0 && height > 0 && rows > 0)
|
||||||
}
|
|
||||||
if (cellHeight < 0 && height > 0 && rows > 0) {
|
|
||||||
cellHeight = (height+padding)/rows;
|
cellHeight = (height+padding)/rows;
|
||||||
dimensionsChanged = true;
|
if (cellWidth != initial.cellWidth || cellHeight != initial.cellHeight) {
|
||||||
}
|
bool positiveCellWidth = cellWidth > 0, positiveCellHeight = cellHeight > 0;
|
||||||
if (dimensionsChanged)
|
|
||||||
lowerToConstraint(cellWidth, cellHeight, cellDimensionsConstraint);
|
lowerToConstraint(cellWidth, cellHeight, cellDimensionsConstraint);
|
||||||
|
if ((cellWidth == 0 && positiveCellWidth) || (cellHeight == 0 && positiveCellHeight))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((cellWidth > 0 && cellWidth-padding-1 <= pxRange) || (cellHeight > 0 && cellHeight-padding-1 <= pxRange)) // cells definitely too small
|
if ((cellWidth > 0 && cellWidth-padding-1 <= pxRange) || (cellHeight > 0 && cellHeight-padding-1 <= pxRange)) // cells definitely too small
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -238,8 +233,11 @@ int GridAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
||||||
|
|
||||||
if (cellWidth > 0 || cellHeight > 0) {
|
if (cellWidth > 0 || cellHeight > 0) {
|
||||||
scale = scaleToFit(glyphs, count, cellWidth, cellHeight, maxBounds, maxWidth, maxHeight);
|
scale = scaleToFit(glyphs, count, cellWidth, cellHeight, maxBounds, maxWidth, maxHeight);
|
||||||
if (scale < minScale)
|
if (scale < minScale) {
|
||||||
return -1;
|
scale = minScale;
|
||||||
|
cutoff = true;
|
||||||
|
maxBounds = getMaxBounds(maxWidth, maxHeight, glyphs, count, scale, unitRange+pxRange/scale);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (width > 0 && height > 0) {
|
else if (width > 0 && height > 0) {
|
||||||
|
|
@ -250,34 +248,33 @@ int GridAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
||||||
int rows = (cellCount+cols-1)/cols;
|
int rows = (cellCount+cols-1)/cols;
|
||||||
int tWidth = (width+padding)/cols;
|
int tWidth = (width+padding)/cols;
|
||||||
int tHeight = (height+padding)/rows;
|
int tHeight = (height+padding)/rows;
|
||||||
if (!(tWidth > 0 && tHeight > 0))
|
|
||||||
continue;
|
|
||||||
lowerToConstraint(tWidth, tHeight, cellDimensionsConstraint);
|
lowerToConstraint(tWidth, tHeight, cellDimensionsConstraint);
|
||||||
double curScale = scaleToFit(glyphs, count, tWidth, tHeight, maxBounds, maxWidth, maxHeight);
|
if (tWidth > 0 && tHeight > 0) {
|
||||||
if (curScale > scale) {
|
double curScale = scaleToFit(glyphs, count, tWidth, tHeight, maxBounds, maxWidth, maxHeight);
|
||||||
scale = curScale;
|
if (curScale > scale) {
|
||||||
bestCols = cols;
|
scale = curScale;
|
||||||
|
bestCols = cols;
|
||||||
|
}
|
||||||
|
if (cols*tWidth == width && curScale > bestAlignedScale) {
|
||||||
|
bestAlignedScale = curScale;
|
||||||
|
bestAlignedCols = cols;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (cols*tWidth == width && curScale > bestAlignedScale) {
|
|
||||||
bestAlignedScale = curScale;
|
|
||||||
bestAlignedCols = cols;
|
|
||||||
}
|
|
||||||
|
|
||||||
cols = (cellCount+q-1)/q;
|
cols = (cellCount+q-1)/q;
|
||||||
rows = (cellCount+cols-1)/cols;
|
rows = (cellCount+cols-1)/cols;
|
||||||
tWidth = (width+padding)/cols;
|
tWidth = (width+padding)/cols;
|
||||||
tHeight = (height+padding)/rows;
|
tHeight = (height+padding)/rows;
|
||||||
if (!(tWidth > 0 && tHeight > 0))
|
|
||||||
continue;
|
|
||||||
lowerToConstraint(tWidth, tHeight, cellDimensionsConstraint);
|
lowerToConstraint(tWidth, tHeight, cellDimensionsConstraint);
|
||||||
curScale = scaleToFit(glyphs, count, tWidth, tHeight, maxBounds, maxWidth, maxHeight);
|
if (tWidth > 0 && tHeight > 0) {
|
||||||
if (curScale > scale) {
|
double curScale = scaleToFit(glyphs, count, tWidth, tHeight, maxBounds, maxWidth, maxHeight);
|
||||||
scale = curScale;
|
if (curScale > scale) {
|
||||||
bestCols = cols;
|
scale = curScale;
|
||||||
}
|
bestCols = cols;
|
||||||
if (cols*tWidth == width && curScale > bestAlignedScale) {
|
}
|
||||||
bestAlignedScale = curScale;
|
if (cols*tWidth == width && curScale > bestAlignedScale) {
|
||||||
bestAlignedCols = cols;
|
bestAlignedScale = curScale;
|
||||||
|
bestAlignedCols = cols;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!bestCols)
|
if (!bestCols)
|
||||||
|
|
@ -294,9 +291,11 @@ int GridAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
||||||
cellHeight = (height+padding)/rows;
|
cellHeight = (height+padding)/rows;
|
||||||
lowerToConstraint(cellWidth, cellHeight, cellDimensionsConstraint);
|
lowerToConstraint(cellWidth, cellHeight, cellDimensionsConstraint);
|
||||||
scale = scaleToFit(glyphs, count, cellWidth, cellHeight, maxBounds, maxWidth, maxHeight);
|
scale = scaleToFit(glyphs, count, cellWidth, cellHeight, maxBounds, maxWidth, maxHeight);
|
||||||
|
if (scale < minScale)
|
||||||
|
scale = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
if (scale <= 0) {
|
||||||
maxBounds = getMaxBounds(maxWidth, maxHeight, glyphs, count, minScale, unitRange+pxRange/minScale);
|
maxBounds = getMaxBounds(maxWidth, maxHeight, glyphs, count, minScale, unitRange+pxRange/minScale);
|
||||||
cellWidth = (int) ceil(maxWidth)+padding+1;
|
cellWidth = (int) ceil(maxWidth)+padding+1;
|
||||||
cellHeight = (int) ceil(maxHeight)+padding+1;
|
cellHeight = (int) ceil(maxHeight)+padding+1;
|
||||||
|
|
@ -306,8 +305,14 @@ int GridAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
||||||
maxBounds = getMaxBounds(maxWidth, maxHeight, glyphs, count, scale = minScale, unitRange+pxRange/minScale);
|
maxBounds = getMaxBounds(maxWidth, maxHeight, glyphs, count, scale = minScale, unitRange+pxRange/minScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!explicitRows && !cellHeightFinal)
|
if (initial.rows < 0 && initial.cellHeight < 0) {
|
||||||
cellHeight = (int) ceil(maxHeight)+padding+1;
|
int optimalCellWidth = cellWidth, optimalCellHeight = (int) ceil(maxHeight)+padding+1;
|
||||||
|
raiseToConstraint(optimalCellWidth, optimalCellHeight, cellDimensionsConstraint);
|
||||||
|
if (optimalCellHeight < cellHeight && optimalCellWidth <= cellWidth) {
|
||||||
|
cellWidth = optimalCellWidth;
|
||||||
|
cellHeight = optimalCellHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
@ -332,8 +337,10 @@ int GridAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
||||||
scale = std::min(hScale, vScale);
|
scale = std::min(hScale, vScale);
|
||||||
else
|
else
|
||||||
scale = hScale+vScale;
|
scale = hScale+vScale;
|
||||||
if (scale < minScale)
|
if (scale < minScale) {
|
||||||
return -1;
|
scale = minScale;
|
||||||
|
cutoff = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (width > 0 && height > 0) {
|
else if (width > 0 && height > 0) {
|
||||||
|
|
@ -344,19 +351,19 @@ int GridAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
||||||
int rows = (cellCount+cols-1)/cols;
|
int rows = (cellCount+cols-1)/cols;
|
||||||
int tWidth = (width+padding)/cols;
|
int tWidth = (width+padding)/cols;
|
||||||
int tHeight = (height+padding)/rows;
|
int tHeight = (height+padding)/rows;
|
||||||
if (!(tWidth > 0 && tHeight > 0))
|
|
||||||
continue;
|
|
||||||
lowerToConstraint(tWidth, tHeight, cellDimensionsConstraint);
|
lowerToConstraint(tWidth, tHeight, cellDimensionsConstraint);
|
||||||
hScale = (tWidth-hSlack-padding-pxRange)/maxWidth;
|
if (tWidth > 0 && tHeight > 0) {
|
||||||
vScale = (tHeight-vSlack-padding-pxRange)/maxHeight;
|
hScale = (tWidth-hSlack-padding-1-pxRange)/maxWidth;
|
||||||
double curScale = std::min(hScale, vScale);
|
vScale = (tHeight-vSlack-padding-1-pxRange)/maxHeight;
|
||||||
if (curScale > scale) {
|
double curScale = std::min(hScale, vScale);
|
||||||
scale = curScale;
|
if (curScale > scale) {
|
||||||
bestCols = cols;
|
scale = curScale;
|
||||||
}
|
bestCols = cols;
|
||||||
if (cols*tWidth == width && curScale > bestAlignedScale) {
|
}
|
||||||
bestAlignedScale = curScale;
|
if (cols*tWidth == width && curScale > bestAlignedScale) {
|
||||||
bestAlignedCols = cols;
|
bestAlignedScale = curScale;
|
||||||
|
bestAlignedCols = cols;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!bestCols)
|
if (!bestCols)
|
||||||
|
|
@ -372,9 +379,11 @@ int GridAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
||||||
cellWidth = (width+padding)/columns;
|
cellWidth = (width+padding)/columns;
|
||||||
cellHeight = (height+padding)/rows;
|
cellHeight = (height+padding)/rows;
|
||||||
lowerToConstraint(cellWidth, cellHeight, cellDimensionsConstraint);
|
lowerToConstraint(cellWidth, cellHeight, cellDimensionsConstraint);
|
||||||
|
if (scale < minScale)
|
||||||
|
scale = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
if (scale <= 0) {
|
||||||
cellWidth = (int) ceil(minScale*maxWidth+pxRange)+hSlack+padding+1;
|
cellWidth = (int) ceil(minScale*maxWidth+pxRange)+hSlack+padding+1;
|
||||||
cellHeight = (int) ceil(minScale*maxHeight+pxRange)+vSlack+padding+1;
|
cellHeight = (int) ceil(minScale*maxHeight+pxRange)+vSlack+padding+1;
|
||||||
raiseToConstraint(cellWidth, cellHeight, cellDimensionsConstraint);
|
raiseToConstraint(cellWidth, cellHeight, cellDimensionsConstraint);
|
||||||
|
|
@ -383,8 +392,14 @@ int GridAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
||||||
scale = std::min(hScale, vScale);
|
scale = std::min(hScale, vScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!explicitRows && !cellHeightFinal)
|
if (initial.rows < 0 && initial.cellHeight < 0) {
|
||||||
cellHeight = (int) ceil(scale*maxHeight+pxRange)+vSlack+padding+1;
|
int optimalCellWidth = cellWidth, optimalCellHeight = (int) ceil(scale*maxHeight+pxRange)+vSlack+padding+1;
|
||||||
|
raiseToConstraint(optimalCellWidth, optimalCellHeight, cellDimensionsConstraint);
|
||||||
|
if (optimalCellHeight < cellHeight && optimalCellWidth <= cellWidth) {
|
||||||
|
cellWidth = optimalCellWidth;
|
||||||
|
cellHeight = optimalCellHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
maxBounds.l *= scale, maxBounds.b *= scale;
|
maxBounds.l *= scale, maxBounds.b *= scale;
|
||||||
maxBounds.r *= scale, maxBounds.t *= scale;
|
maxBounds.r *= scale, maxBounds.t *= scale;
|
||||||
maxWidth *= scale, maxHeight *= scale;
|
maxWidth *= scale, maxHeight *= scale;
|
||||||
|
|
@ -393,11 +408,14 @@ int GridAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
maxBounds = getMaxBounds(maxWidth, maxHeight, glyphs, count, scale, unitRange+pxRange/scale);
|
maxBounds = getMaxBounds(maxWidth, maxHeight, glyphs, count, scale, unitRange+pxRange/scale);
|
||||||
|
int optimalCellWidth = (int) ceil(maxWidth)+padding+1;
|
||||||
|
int optimalCellHeight = (int) ceil(maxHeight)+padding+1;
|
||||||
if (cellWidth < 0 || cellHeight < 0) {
|
if (cellWidth < 0 || cellHeight < 0) {
|
||||||
cellWidth = (int) ceil(maxWidth)+padding+1;
|
cellWidth = optimalCellWidth;
|
||||||
cellHeight = (int) ceil(maxHeight)+padding+1;
|
cellHeight = optimalCellHeight;
|
||||||
raiseToConstraint(cellWidth, cellHeight, cellDimensionsConstraint);
|
raiseToConstraint(cellWidth, cellHeight, cellDimensionsConstraint);
|
||||||
}
|
} else if (cellWidth < optimalCellWidth || cellHeight < optimalCellHeight)
|
||||||
|
cutoff = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute fixed origin
|
// Compute fixed origin
|
||||||
|
|
@ -445,17 +463,27 @@ int GridAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
||||||
}
|
}
|
||||||
width = columns*cellWidth, height = rows*cellHeight;
|
width = columns*cellWidth, height = rows*cellHeight;
|
||||||
raiseToConstraint(width, height, dimensionsConstraint);
|
raiseToConstraint(width, height, dimensionsConstraint);
|
||||||
|
// raiseToConstraint may have increased dimensions significantly, rerun if cell dimensions can be optimized.
|
||||||
|
if (dimensionsConstraint != DimensionsConstraint::NONE && initial.cellWidth < 0 && initial.cellHeight < 0) {
|
||||||
|
cellWidth = initial.cellWidth;
|
||||||
|
cellHeight = initial.cellHeight;
|
||||||
|
columns = initial.columns;
|
||||||
|
rows = initial.rows;
|
||||||
|
scale = initial.scale;
|
||||||
|
return pack(glyphs, count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (columns < 0) {
|
if (columns < 0) {
|
||||||
columns = (width+padding)/cellWidth;
|
columns = (width+padding)/cellWidth;
|
||||||
rows = (cellCount+columns-1)/columns;
|
rows = (cellCount+columns-1)/columns;
|
||||||
}
|
}
|
||||||
|
if (rows*cellHeight > height)
|
||||||
|
rows = height/cellHeight;
|
||||||
|
|
||||||
int col = 0, row = 0;
|
int col = 0, row = 0;
|
||||||
for (GlyphGeometry *glyph = glyphs, *end = glyphs+count; glyph < end; ++glyph) {
|
for (GlyphGeometry *glyph = glyphs, *end = glyphs+count; glyph < end; ++glyph) {
|
||||||
if (!glyph->isWhitespace()) {
|
if (!glyph->isWhitespace()) {
|
||||||
Rectangle rect = { };
|
|
||||||
glyph->frameBox(scale, unitRange+pxRange/scale, miterLimit, cellWidth-padding, cellHeight-padding, hFixed ? &fixedX : nullptr, vFixed ? &fixedY : nullptr, pxAlignOriginX, pxAlignOriginY);
|
glyph->frameBox(scale, unitRange+pxRange/scale, miterLimit, cellWidth-padding, cellHeight-padding, hFixed ? &fixedX : nullptr, vFixed ? &fixedY : nullptr, pxAlignOriginX, pxAlignOriginY);
|
||||||
glyph->placeBox(col*cellWidth, height-(row+1)*cellHeight);
|
glyph->placeBox(col*cellWidth, height-(row+1)*cellHeight);
|
||||||
if (++col >= columns) {
|
if (++col >= columns) {
|
||||||
|
|
@ -567,7 +595,7 @@ double GridAtlasPacker::getScale() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
double GridAtlasPacker::getPixelRange() const {
|
double GridAtlasPacker::getPixelRange() const {
|
||||||
return pxRange;
|
return pxRange+scale*unitRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridAtlasPacker::getFixedOrigin(double &x, double &y) {
|
void GridAtlasPacker::getFixedOrigin(double &x, double &y) {
|
||||||
|
|
@ -575,4 +603,8 @@ void GridAtlasPacker::getFixedOrigin(double &x, double &y) {
|
||||||
y = fixedY-.5/scale;
|
y = fixedY-.5/scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GridAtlasPacker::hasCutoff() const {
|
||||||
|
return cutoff;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,14 +51,20 @@ public:
|
||||||
|
|
||||||
/// Outputs the atlas's final dimensions
|
/// Outputs the atlas's final dimensions
|
||||||
void getDimensions(int &width, int &height) const;
|
void getDimensions(int &width, int &height) const;
|
||||||
|
/// Outputs the horizontal and vertical difference between the bottom left corners of consecutive grid cells
|
||||||
void getCellDimensions(int &width, int &height) const;
|
void getCellDimensions(int &width, int &height) const;
|
||||||
|
/// Returns the final number of grid columns
|
||||||
int getColumns() const;
|
int getColumns() const;
|
||||||
|
/// Returns the final number of grid rows
|
||||||
int getRows() const;
|
int getRows() const;
|
||||||
/// Returns the final glyph scale
|
/// Returns the final glyph scale
|
||||||
double getScale() const;
|
double getScale() const;
|
||||||
/// Returns the final combined pixel range (including converted unit range)
|
/// Returns the final combined pixel range (including converted unit range)
|
||||||
double getPixelRange() const;
|
double getPixelRange() const;
|
||||||
|
/// Outputs the position of the origin within each cell, each value is only valid if the origin is fixed in the respective dimension
|
||||||
void getFixedOrigin(double &x, double &y);
|
void getFixedOrigin(double &x, double &y);
|
||||||
|
/// Returns true if the explicitly constrained cell dimensions aren't large enough to fit each glyph fully
|
||||||
|
bool hasCutoff() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int columns, rows;
|
int columns, rows;
|
||||||
|
|
@ -77,6 +83,7 @@ private:
|
||||||
bool pxAlignOriginX, pxAlignOriginY;
|
bool pxAlignOriginX, pxAlignOriginY;
|
||||||
double scaleMaximizationTolerance;
|
double scaleMaximizationTolerance;
|
||||||
double alignedColumnsBias;
|
double alignedColumnsBias;
|
||||||
|
bool cutoff;
|
||||||
|
|
||||||
static void lowerToConstraint(int &width, int &height, DimensionsConstraint constraint);
|
static void lowerToConstraint(int &width, int &height, DimensionsConstraint constraint);
|
||||||
static void raiseToConstraint(int &width, int &height, DimensionsConstraint constraint);
|
static void raiseToConstraint(int &width, int &height, DimensionsConstraint constraint);
|
||||||
|
|
|
||||||
|
|
@ -116,8 +116,6 @@ int TightAtlasPacker::pack(GlyphGeometry *glyphs, int count) {
|
||||||
scale = packAndScale(glyphs, count);
|
scale = packAndScale(glyphs, count);
|
||||||
if (scale <= 0)
|
if (scale <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
pxRange += scale*unitRange;
|
|
||||||
unitRange = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,7 +172,7 @@ double TightAtlasPacker::getScale() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
double TightAtlasPacker::getPixelRange() const {
|
double TightAtlasPacker::getPixelRange() const {
|
||||||
return pxRange;
|
return pxRange+scale*unitRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1123,6 +1123,8 @@ int main(int argc, const char * const *argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (atlasPacker.hasCutoff())
|
||||||
|
fputs("Warning: Grid cell too constrained to fully fit all glyphs, some may be cut off!\n", stderr);
|
||||||
atlasPacker.getDimensions(config.width, config.height);
|
atlasPacker.getDimensions(config.width, config.height);
|
||||||
if (!(config.width > 0 && config.height > 0))
|
if (!(config.width > 0 && config.height > 0))
|
||||||
ABORT("Unable to determine atlas size.");
|
ABORT("Unable to determine atlas size.");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue