Updated MSDFgen, improved DynamicAtlas API

This commit is contained in:
Chlumsky 2021-12-07 18:04:16 +01:00
parent b5d54f3012
commit dadc65c85c
8 changed files with 40 additions and 12 deletions

View File

@ -16,11 +16,18 @@ template <class AtlasGenerator>
class DynamicAtlas { class DynamicAtlas {
public: public:
enum ChangeFlag {
NO_CHANGE = 0x00,
RESIZED = 0x01,
REARRANGED = 0x02
};
typedef int ChangeFlags;
DynamicAtlas(); DynamicAtlas();
/// Creates with a configured generator. The generator must not contain any prior glyphs! /// Creates with a configured generator. The generator must not contain any prior glyphs!
explicit DynamicAtlas(AtlasGenerator &&generator); explicit DynamicAtlas(AtlasGenerator &&generator);
/// Adds a batch of glyphs. Adding more than one glyph at a time may improve packing efficiency /// Adds a batch of glyphs. Adding more than one glyph at a time may improve packing efficiency
void add(GlyphGeometry *glyphs, int count); ChangeFlags add(GlyphGeometry *glyphs, int count);
/// Allows access to generator. Do not add glyphs to the generator directly! /// Allows access to generator. Do not add glyphs to the generator directly!
AtlasGenerator & atlasGenerator(); AtlasGenerator & atlasGenerator();
const AtlasGenerator & atlasGenerator() const; const AtlasGenerator & atlasGenerator() const;

View File

@ -10,7 +10,8 @@ template <class AtlasGenerator>
DynamicAtlas<AtlasGenerator>::DynamicAtlas(AtlasGenerator &&generator) : generator((AtlasGenerator &&) generator), glyphCount(0), side(0), totalArea(0), padding(0) { } DynamicAtlas<AtlasGenerator>::DynamicAtlas(AtlasGenerator &&generator) : generator((AtlasGenerator &&) generator), glyphCount(0), side(0), totalArea(0), padding(0) { }
template <class AtlasGenerator> template <class AtlasGenerator>
void DynamicAtlas<AtlasGenerator>::add(GlyphGeometry *glyphs, int count) { typename DynamicAtlas<AtlasGenerator>::ChangeFlags DynamicAtlas<AtlasGenerator>::add(GlyphGeometry *glyphs, int count) {
ChangeFlags changeFlags = 0;
int start = rectangles.size(); int start = rectangles.size();
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
if (!glyphs[i].isWhitespace()) { if (!glyphs[i].isWhitespace()) {
@ -27,14 +28,14 @@ void DynamicAtlas<AtlasGenerator>::add(GlyphGeometry *glyphs, int count) {
} }
} }
if ((int) rectangles.size() > start) { if ((int) rectangles.size() > start) {
int oldSide = side;
int packerStart = start; int packerStart = start;
while (packer.pack(rectangles.data()+packerStart, rectangles.size()-packerStart) > 0) { while (packer.pack(rectangles.data()+packerStart, rectangles.size()-packerStart) > 0) {
side = side+!side<<1; side = (side+!side)<<1;
while (side*side < totalArea) while (side*side < totalArea)
side <<= 1; side <<= 1;
packer = RectanglePacker(side+padding, side+padding); packer = RectanglePacker(side+padding, side+padding);
packerStart = 0; packerStart = 0;
changeFlags |= RESIZED;
} }
if (packerStart < start) { if (packerStart < start) {
for (int i = 0; i < start; ++i) { for (int i = 0; i < start; ++i) {
@ -44,7 +45,8 @@ void DynamicAtlas<AtlasGenerator>::add(GlyphGeometry *glyphs, int count) {
remap.target.y = rectangles[i].y; remap.target.y = rectangles[i].y;
} }
generator.rearrange(side, side, remapBuffer.data(), start); generator.rearrange(side, side, remapBuffer.data(), start);
} else if (side != oldSide) changeFlags |= REARRANGED;
} else if (changeFlags&RESIZED)
generator.resize(side, side); generator.resize(side, side);
for (int i = start; i < (int) rectangles.size(); ++i) { for (int i = start; i < (int) rectangles.size(); ++i) {
remapBuffer[i].target.x = rectangles[i].x; remapBuffer[i].target.x = rectangles[i].x;
@ -54,6 +56,7 @@ void DynamicAtlas<AtlasGenerator>::add(GlyphGeometry *glyphs, int count) {
} }
generator.generate(glyphs, count); generator.generate(glyphs, count);
glyphCount += count; glyphCount += count;
return changeFlags;
} }
template <class AtlasGenerator> template <class AtlasGenerator>

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include "Rectangle.h"
namespace msdf_atlas { namespace msdf_atlas {
/// The glyph box - its bounds in plane and atlas /// The glyph box - its bounds in plane and atlas
@ -10,9 +12,7 @@ struct GlyphBox {
struct { struct {
double l, b, r, t; double l, b, r, t;
} bounds; } bounds;
struct { Rectangle rect;
int x, y, w, h;
} rect;
}; };

View File

@ -78,6 +78,10 @@ void GlyphGeometry::placeBox(int x, int y) {
box.rect.x = x, box.rect.y = y; box.rect.x = x, box.rect.y = y;
} }
void GlyphGeometry::setBoxRect(const Rectangle &rect) {
box.rect = rect;
}
int GlyphGeometry::getIndex() const { int GlyphGeometry::getIndex() const {
return index; return index;
} }
@ -108,6 +112,10 @@ double GlyphGeometry::getAdvance() const {
return advance; return advance;
} }
Rectangle GlyphGeometry::getBoxRect() const {
return box.rect;
}
void GlyphGeometry::getBoxRect(int &x, int &y, int &w, int &h) const { void GlyphGeometry::getBoxRect(int &x, int &y, int &w, int &h) const {
x = box.rect.x, y = box.rect.y; x = box.rect.x, y = box.rect.y;
w = box.rect.w, h = box.rect.h; w = box.rect.w, h = box.rect.h;

View File

@ -4,6 +4,7 @@
#include <msdfgen.h> #include <msdfgen.h>
#include <msdfgen-ext.h> #include <msdfgen-ext.h>
#include "types.h" #include "types.h"
#include "Rectangle.h"
#include "GlyphBox.h" #include "GlyphBox.h"
namespace msdf_atlas { namespace msdf_atlas {
@ -22,6 +23,8 @@ public:
void wrapBox(double scale, double range, double miterLimit); void wrapBox(double scale, double range, double miterLimit);
/// Sets the glyph's box's position in the atlas /// Sets the glyph's box's position in the atlas
void placeBox(int x, int y); void placeBox(int x, int y);
/// Sets the glyph's box's rectangle in the atlas
void setBoxRect(const Rectangle &rect);
/// Returns the glyph's index within the font /// Returns the glyph's index within the font
int getIndex() const; int getIndex() const;
/// Returns the glyph's index as a msdfgen::GlyphIndex /// Returns the glyph's index as a msdfgen::GlyphIndex
@ -34,6 +37,8 @@ public:
const msdfgen::Shape & getShape() const; const msdfgen::Shape & getShape() const;
/// Returns the glyph's advance /// Returns the glyph's advance
double getAdvance() const; double getAdvance() const;
/// Returns the glyph's box in the atlas
Rectangle getBoxRect() const;
/// Outputs the position and dimensions of the glyph's box in the atlas /// Outputs the position and dimensions of the glyph's box in the atlas
void getBoxRect(int &x, int &y, int &w, int &h) const; void getBoxRect(int &x, int &y, int &w, int &h) const;
/// Outputs the dimensions of the glyph's box in the atlas /// Outputs the dimensions of the glyph's box in the atlas
@ -63,9 +68,7 @@ private:
msdfgen::Shape::Bounds bounds; msdfgen::Shape::Bounds bounds;
double advance; double advance;
struct { struct {
struct { Rectangle rect;
int x, y, w, h;
} rect;
double range; double range;
double scale; double scale;
msdfgen::Vector2 translate; msdfgen::Vector2 translate;

View File

@ -29,6 +29,8 @@ public:
void setThreadCount(int threadCount); void setThreadCount(int threadCount);
/// Allows access to the underlying AtlasStorage /// Allows access to the underlying AtlasStorage
const AtlasStorage & atlasStorage() const; const AtlasStorage & atlasStorage() const;
/// Returns the layout of the contained glyphs as a list of GlyphBoxes
const std::vector<GlyphBox> & getLayout() const;
private: private:
AtlasStorage storage; AtlasStorage storage;

View File

@ -74,4 +74,9 @@ const AtlasStorage & ImmediateAtlasGenerator<T, N, GEN_FN, AtlasStorage>::atlasS
return storage; return storage;
} }
template <typename T, int N, GeneratorFunction<T, N> GEN_FN, class AtlasStorage>
const std::vector<GlyphBox> & ImmediateAtlasGenerator<T, N, GEN_FN, AtlasStorage>::getLayout() const {
return layout;
}
} }

@ -1 +1 @@
Subproject commit d07fa1d2c8088f87463182a05cab9bee29844e70 Subproject commit 64a91eec3ca3787e6f78b4c99fcd3052ad3e37c0