diff --git a/msdf-atlas-gen/GlyphGeometry.cpp b/msdf-atlas-gen/GlyphGeometry.cpp index 72684d0..13aee57 100644 --- a/msdf-atlas-gen/GlyphGeometry.cpp +++ b/msdf-atlas-gen/GlyphGeometry.cpp @@ -52,6 +52,31 @@ void GlyphGeometry::edgeColoring(void (*fn)(msdfgen::Shape &, double, unsigned l } void GlyphGeometry::wrapBox(double scale, double range, double miterLimit) { + scale *= geometryScale; + range /= geometryScale; + box.range = range; + box.scale = scale; + if (bounds.l < bounds.r && bounds.b < bounds.t) { + double l = bounds.l, b = bounds.b, r = bounds.r, t = bounds.t; + l -= .5*range, b -= .5*range; + r += .5*range, t += .5*range; + if (miterLimit > 0) + shape.boundMiters(l, b, r, t, .5*range, miterLimit, 1); + int sl = (int) floor(scale*l-.5); + int sb = (int) floor(scale*b-.5); + int sr = (int) ceil(scale*r+.5); + int st = (int) ceil(scale*t+.5); + box.rect.w = sr-sl; + box.rect.h = st-sb; + box.translate.x = -sl/scale; + box.translate.y = -sb/scale; + } else { + box.rect.w = 0, box.rect.h = 0; + box.translate = msdfgen::Vector2(); + } +} + +void GlyphGeometry::wrapBoxUnaligned(double scale, double range, double miterLimit) { scale *= geometryScale; range /= geometryScale; box.range = range; diff --git a/msdf-atlas-gen/GlyphGeometry.h b/msdf-atlas-gen/GlyphGeometry.h index f1c5d2a..10a791c 100644 --- a/msdf-atlas-gen/GlyphGeometry.h +++ b/msdf-atlas-gen/GlyphGeometry.h @@ -21,6 +21,8 @@ public: void edgeColoring(void (*fn)(msdfgen::Shape &, double, unsigned long long), double angleThreshold, unsigned long long seed); /// Computes the dimensions of the glyph's box as well as the transformation for the generator function void wrapBox(double scale, double range, double miterLimit); + /// Computes the dimensions of the glyph's box and the transformation for the generator function, allowing origin to be located at a non-integer coordinate + void wrapBoxUnaligned(double scale, double range, double miterLimit); /// Sets the glyph's box's position in the atlas void placeBox(int x, int y); /// Sets the glyph's box's rectangle in the atlas diff --git a/msdf-atlas-gen/TightAtlasPacker.cpp b/msdf-atlas-gen/TightAtlasPacker.cpp index 5c623ea..1396cdf 100644 --- a/msdf-atlas-gen/TightAtlasPacker.cpp +++ b/msdf-atlas-gen/TightAtlasPacker.cpp @@ -8,7 +8,20 @@ namespace msdf_atlas { -int TightAtlasPacker::tryPack(GlyphGeometry *glyphs, int count, DimensionsConstraint dimensionsConstraint, int &width, int &height, int padding, double scale, double range, double miterLimit) { +TightAtlasPacker::TightAtlasPacker() : + width(-1), height(-1), + padding(0), + dimensionsConstraint(DimensionsConstraint::POWER_OF_TWO_SQUARE), + scale(-1), + minScale(1), + unitRange(0), + pxRange(0), + miterLimit(0), + scaleMaximizationTolerance(.001) +{ } + +int TightAtlasPacker::tryPack(GlyphGeometry *glyphs, int count, DimensionsConstraint dimensionsConstraint, int &width, int &height, double scale) const { + double range = unitRange+pxRange/scale; // Wrap glyphs into boxes std::vector rectangles; std::vector rectangleGlyphs; @@ -64,9 +77,10 @@ int TightAtlasPacker::tryPack(GlyphGeometry *glyphs, int count, DimensionsConstr return 0; } -double TightAtlasPacker::packAndScale(GlyphGeometry *glyphs, int count, int width, int height, int padding, double unitRange, double pxRange, double miterLimit, double tolerance) { +double TightAtlasPacker::packAndScale(GlyphGeometry *glyphs, int count) const { bool lastResult = false; - #define TRY_PACK(scale) (lastResult = !tryPack(glyphs, count, DimensionsConstraint(), width, height, padding, (scale), unitRange+pxRange/(scale), miterLimit)) + int w = width, h = height; + #define TRY_PACK(scale) (lastResult = !tryPack(glyphs, count, DimensionsConstraint(), w, h, (scale))) double minScale = 1, maxScale = 1; if (TRY_PACK(1)) { while (maxScale < 1e+32 && ((maxScale = 2*minScale), TRY_PACK(maxScale))) @@ -77,7 +91,7 @@ double TightAtlasPacker::packAndScale(GlyphGeometry *glyphs, int count, int widt } if (minScale == maxScale) return 0; - while (minScale/maxScale < 1-tolerance) { + while (minScale/maxScale < 1-scaleMaximizationTolerance) { double midScale = .5*(minScale+maxScale); if (TRY_PACK(midScale)) minScale = midScale; @@ -89,27 +103,15 @@ double TightAtlasPacker::packAndScale(GlyphGeometry *glyphs, int count, int widt return minScale; } -TightAtlasPacker::TightAtlasPacker() : - width(-1), height(-1), - padding(0), - dimensionsConstraint(DimensionsConstraint::POWER_OF_TWO_SQUARE), - scale(-1), - minScale(1), - unitRange(0), - pxRange(0), - miterLimit(0), - scaleMaximizationTolerance(.001) -{ } - int TightAtlasPacker::pack(GlyphGeometry *glyphs, int count) { double initialScale = scale > 0 ? scale : minScale; if (initialScale > 0) { - if (int remaining = tryPack(glyphs, count, dimensionsConstraint, width, height, padding, initialScale, unitRange+pxRange/initialScale, miterLimit)) + if (int remaining = tryPack(glyphs, count, dimensionsConstraint, width, height, initialScale)) return remaining; } else if (width < 0 || height < 0) return -1; if (scale <= 0) - scale = packAndScale(glyphs, count, width, height, padding, unitRange, pxRange, miterLimit, scaleMaximizationTolerance); + scale = packAndScale(glyphs, count); if (scale <= 0) return -1; pxRange += scale*unitRange; diff --git a/msdf-atlas-gen/TightAtlasPacker.h b/msdf-atlas-gen/TightAtlasPacker.h index 35bb2a9..7c54feb 100644 --- a/msdf-atlas-gen/TightAtlasPacker.h +++ b/msdf-atlas-gen/TightAtlasPacker.h @@ -63,8 +63,8 @@ private: double miterLimit; double scaleMaximizationTolerance; - static int tryPack(GlyphGeometry *glyphs, int count, DimensionsConstraint dimensionsConstraint, int &width, int &height, int padding, double scale, double range, double miterLimit); - static double packAndScale(GlyphGeometry *glyphs, int count, int width, int height, int padding, double unitRange, double pxRange, double miterLimit, double tolerance); + int tryPack(GlyphGeometry *glyphs, int count, DimensionsConstraint dimensionsConstraint, int &width, int &height, double scale) const; + double packAndScale(GlyphGeometry *glyphs, int count) const; };