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 {
public:
enum ChangeFlag {
NO_CHANGE = 0x00,
RESIZED = 0x01,
REARRANGED = 0x02
};
typedef int ChangeFlags;
DynamicAtlas();
/// Creates with a configured generator. The generator must not contain any prior glyphs!
explicit DynamicAtlas(AtlasGenerator &&generator);
/// 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!
AtlasGenerator & atlasGenerator();
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) { }
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();
for (int i = 0; i < count; ++i) {
if (!glyphs[i].isWhitespace()) {
@ -27,14 +28,14 @@ void DynamicAtlas<AtlasGenerator>::add(GlyphGeometry *glyphs, int count) {
}
}
if ((int) rectangles.size() > start) {
int oldSide = side;
int packerStart = start;
while (packer.pack(rectangles.data()+packerStart, rectangles.size()-packerStart) > 0) {
side = side+!side<<1;
side = (side+!side)<<1;
while (side*side < totalArea)
side <<= 1;
packer = RectanglePacker(side+padding, side+padding);
packerStart = 0;
changeFlags |= RESIZED;
}
if (packerStart < start) {
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;
}
generator.rearrange(side, side, remapBuffer.data(), start);
} else if (side != oldSide)
changeFlags |= REARRANGED;
} else if (changeFlags&RESIZED)
generator.resize(side, side);
for (int i = start; i < (int) rectangles.size(); ++i) {
remapBuffer[i].target.x = rectangles[i].x;
@ -54,6 +56,7 @@ void DynamicAtlas<AtlasGenerator>::add(GlyphGeometry *glyphs, int count) {
}
generator.generate(glyphs, count);
glyphCount += count;
return changeFlags;
}
template <class AtlasGenerator>

View File

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

View File

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

View File

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

View File

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

View File

@ -74,4 +74,9 @@ const AtlasStorage & ImmediateAtlasGenerator<T, N, GEN_FN, AtlasStorage>::atlasS
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