Integrate BitmapSection references

This commit is contained in:
Chlumsky
2025-12-06 15:11:36 +01:00
parent 94390ed367
commit c76a323199
22 changed files with 272 additions and 193 deletions

View File

@@ -37,6 +37,6 @@ struct GeneratorAttributes {
/// A function that generates the bitmap for a single glyph
template <typename T, int N>
using GeneratorFunction = void (*)(const msdfgen::BitmapRef<T, N> &, const GlyphGeometry &, const GeneratorAttributes &);
using GeneratorFunction = void (*)(const msdfgen::BitmapSection<T, N> &, const GlyphGeometry &, const GeneratorAttributes &);
}

View File

@@ -25,10 +25,10 @@ public:
AtlasStorage(const AtlasStorage &orig, int width, int height, const Remap *remapping, int count);
/// Stores a subsection at x, y into the atlas storage. May be implemented for only some T, N
template <typename T, int N>
void put(int x, int y, const msdfgen::BitmapConstRef<T, N> &subBitmap);
void put(int x, int y, const msdfgen::BitmapConstSection<T, N> &subBitmap);
/// Retrieves a subsection at x, y from the atlas storage. May be implemented for only some T, N
template <typename T, int N>
void get(int x, int y, const msdfgen::BitmapRef<T, N> &subBitmap) const;
void get(int x, int y, const msdfgen::BitmapSection<T, N> &subBitmap) const;
};

View File

@@ -12,16 +12,18 @@ class BitmapAtlasStorage {
public:
BitmapAtlasStorage();
BitmapAtlasStorage(int width, int height);
explicit BitmapAtlasStorage(const msdfgen::BitmapConstRef<T, N> &bitmap);
explicit BitmapAtlasStorage(const msdfgen::BitmapConstSection<T, N> &bitmap);
explicit BitmapAtlasStorage(msdfgen::Bitmap<T, N> &&bitmap);
BitmapAtlasStorage(const BitmapAtlasStorage<T, N> &orig, int width, int height);
BitmapAtlasStorage(const BitmapAtlasStorage<T, N> &orig, int width, int height, const Remap *remapping, int count);
operator msdfgen::BitmapConstSection<T, N>() const;
operator msdfgen::BitmapConstRef<T, N>() const;
operator msdfgen::BitmapSection<T, N>();
operator msdfgen::BitmapRef<T, N>();
operator msdfgen::Bitmap<T, N>() &&;
template <typename S>
void put(int x, int y, const msdfgen::BitmapConstRef<S, N> &subBitmap);
void get(int x, int y, const msdfgen::BitmapRef<T, N> &subBitmap) const;
void put(int x, int y, const msdfgen::BitmapConstSection<S, N> &subBitmap);
void get(int x, int y, const msdfgen::BitmapSection<T, N> &subBitmap) const;
private:
msdfgen::Bitmap<T, N> bitmap;

View File

@@ -16,7 +16,7 @@ BitmapAtlasStorage<T, N>::BitmapAtlasStorage(int width, int height) : bitmap(wid
}
template <typename T, int N>
BitmapAtlasStorage<T, N>::BitmapAtlasStorage(const msdfgen::BitmapConstRef<T, N> &bitmap) : bitmap(bitmap) { }
BitmapAtlasStorage<T, N>::BitmapAtlasStorage(const msdfgen::BitmapConstSection<T, N> &bitmap) : bitmap(bitmap) { }
template <typename T, int N>
BitmapAtlasStorage<T, N>::BitmapAtlasStorage(msdfgen::Bitmap<T, N> &&bitmap) : bitmap((msdfgen::Bitmap<T, N> &&) bitmap) { }
@@ -36,11 +36,21 @@ BitmapAtlasStorage<T, N>::BitmapAtlasStorage(const BitmapAtlasStorage<T, N> &ori
}
}
template <typename T, int N>
BitmapAtlasStorage<T, N>::operator msdfgen::BitmapConstSection<T, N>() const {
return bitmap;
}
template <typename T, int N>
BitmapAtlasStorage<T, N>::operator msdfgen::BitmapConstRef<T, N>() const {
return bitmap;
}
template <typename T, int N>
BitmapAtlasStorage<T, N>::operator msdfgen::BitmapSection<T, N>() {
return bitmap;
}
template <typename T, int N>
BitmapAtlasStorage<T, N>::operator msdfgen::BitmapRef<T, N>() {
return bitmap;
@@ -53,12 +63,12 @@ BitmapAtlasStorage<T, N>::operator msdfgen::Bitmap<T, N>() && {
template <typename T, int N>
template <typename S>
void BitmapAtlasStorage<T, N>::put(int x, int y, const msdfgen::BitmapConstRef<S, N> &subBitmap) {
void BitmapAtlasStorage<T, N>::put(int x, int y, const msdfgen::BitmapConstSection<S, N> &subBitmap) {
blit(bitmap, subBitmap, x, y, 0, 0, subBitmap.width, subBitmap.height);
}
template <typename T, int N>
void BitmapAtlasStorage<T, N>::get(int x, int y, const msdfgen::BitmapRef<T, N> &subBitmap) const {
void BitmapAtlasStorage<T, N>::get(int x, int y, const msdfgen::BitmapSection<T, N> &subBitmap) const {
blit(subBitmap, bitmap, 0, 0, x, y, subBitmap.width, subBitmap.height);
}

View File

@@ -41,7 +41,7 @@ void ImmediateAtlasGenerator<T, N, GEN_FN, AtlasStorage>::generate(const GlyphGe
glyph.getBoxRect(l, b, w, h);
msdfgen::BitmapRef<T, N> glyphBitmap(glyphBuffer.data()+threadNo*threadBufferSize, w, h);
GEN_FN(glyphBitmap, glyph, threadAttributes[threadNo]);
storage.put(l, b, msdfgen::BitmapConstRef<T, N>(glyphBitmap));
storage.put(l, b, msdfgen::BitmapConstSection<T, N>(glyphBitmap));
}
return true;
}, count).finish(threadCount);

View File

@@ -38,7 +38,7 @@ static artery_font::CodepointType convertCodepointType(GlyphIdentifierType glyph
}
template <typename T, int N>
static bool encodeTiff(std::vector<byte> &output, const msdfgen::BitmapConstRef<T, N> &atlas) {
static bool encodeTiff(std::vector<byte> &output, const msdfgen::BitmapConstSection<T, N> &atlas) {
// TODO
return false;
}
@@ -56,7 +56,7 @@ artery_font::PixelFormat getPixelFormat<float>() {
}
template <typename REAL, typename T, int N>
bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef<T, N> &atlas, const char *filename, const ArteryFontExportProperties &properties) {
bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstSection<T, N> &atlas, const char *filename, const ArteryFontExportProperties &properties) {
artery_font::StdArteryFont<REAL> arfont = { };
arfont.metadataFormat = artery_font::METADATA_NONE;
@@ -161,20 +161,21 @@ bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::B
return false;
image.encoding = artery_font::IMAGE_RAW_BINARY;
image.rawBinaryFormat.rowLength = N*sizeof(T)*atlas.width;
image.data = artery_font::StdByteArray(N*sizeof(T)*atlas.width*atlas.height);
switch (properties.yDirection) {
case YDirection::BOTTOM_UP:
switch (atlas.yOrientation) {
case msdfgen::Y_UPWARD:
image.rawBinaryFormat.orientation = artery_font::ORIENTATION_BOTTOM_UP;
memcpy((byte *) image.data, atlas.pixels, N*sizeof(T)*atlas.width*atlas.height);
break;
case YDirection::TOP_DOWN: {
case msdfgen::Y_DOWNWARD:
image.rawBinaryFormat.orientation = artery_font::ORIENTATION_TOP_DOWN;
byte *imageData = (byte *) image.data;
for (int y = atlas.height-1; y >= 0; --y) {
memcpy(imageData, atlas.pixels+N*atlas.width*y, N*sizeof(T)*atlas.width);
imageData += N*sizeof(T)*atlas.width;
}
break;
}
{
size_t rowSize = N*sizeof(T)*atlas.width;
image.data = artery_font::StdByteArray(rowSize*atlas.height);
byte *imageData = (byte *) image.data;
for (int y = 0; y < atlas.height; ++y) {
memcpy(imageData, atlas(0, y), rowSize);
imageData += rowSize;
}
}
break;
@@ -186,12 +187,12 @@ bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::B
return artery_font::writeFile(arfont, filename);
}
template bool exportArteryFont<float>(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef<byte, 1> &atlas, const char *filename, const ArteryFontExportProperties &properties);
template bool exportArteryFont<float>(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef<byte, 3> &atlas, const char *filename, const ArteryFontExportProperties &properties);
template bool exportArteryFont<float>(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef<byte, 4> &atlas, const char *filename, const ArteryFontExportProperties &properties);
template bool exportArteryFont<float>(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef<float, 1> &atlas, const char *filename, const ArteryFontExportProperties &properties);
template bool exportArteryFont<float>(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef<float, 3> &atlas, const char *filename, const ArteryFontExportProperties &properties);
template bool exportArteryFont<float>(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef<float, 4> &atlas, const char *filename, const ArteryFontExportProperties &properties);
template bool exportArteryFont<float>(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstSection<byte, 1> &atlas, const char *filename, const ArteryFontExportProperties &properties);
template bool exportArteryFont<float>(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstSection<byte, 3> &atlas, const char *filename, const ArteryFontExportProperties &properties);
template bool exportArteryFont<float>(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstSection<byte, 4> &atlas, const char *filename, const ArteryFontExportProperties &properties);
template bool exportArteryFont<float>(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstSection<float, 1> &atlas, const char *filename, const ArteryFontExportProperties &properties);
template bool exportArteryFont<float>(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstSection<float, 3> &atlas, const char *filename, const ArteryFontExportProperties &properties);
template bool exportArteryFont<float>(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstSection<float, 4> &atlas, const char *filename, const ArteryFontExportProperties &properties);
}

View File

@@ -15,12 +15,11 @@ struct ArteryFontExportProperties {
msdfgen::Range pxRange;
ImageType imageType;
ImageFormat imageFormat;
YDirection yDirection;
};
/// Encodes the atlas bitmap and its layout into an Artery Atlas Font file
template <typename REAL, typename T, int N>
bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef<T, N> &atlas, const char *filename, const ArteryFontExportProperties &properties);
bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstSection<T, N> &atlas, const char *filename, const ArteryFontExportProperties &properties);
}

View File

@@ -6,7 +6,7 @@
namespace msdf_atlas {
#define BOUND_AREA() { \
#define BOUND_SECTION() { \
if (dx < 0) w += dx, sx -= dx, dx = 0; \
if (dy < 0) h += dy, sy -= dy, dy = 0; \
if (sx < 0) w += sx, dx -= sx, sx = 0; \
@@ -16,13 +16,23 @@ namespace msdf_atlas {
}
template <typename T, int N>
void blitSameType(const msdfgen::BitmapRef<T, N> &dst, const msdfgen::BitmapConstRef<T, N> &src, int dx, int dy, int sx, int sy, int w, int h) {
BOUND_AREA();
for (int y = 0; y < h; ++y)
memcpy(dst(dx, dy+y), src(sx, sy+y), sizeof(T)*N*w);
static void blitSameType(const msdfgen::BitmapSection<T, N> &dst, const msdfgen::BitmapConstSection<T, N> &src) {
int width = std::min(dst.width, src.width), height = std::min(dst.height, src.height);
size_t rowSize = sizeof(T)*N*width;
for (int y = 0; y < height; ++y)
memcpy(dst(0, y), src(0, y), rowSize);
}
#define BLIT_SAME_TYPE_IMPL(T, N) void blit(const msdfgen::BitmapRef<T, N> &dst, const msdfgen::BitmapConstRef<T, N> &src, int dx, int dy, int sx, int sy, int w, int h) { blitSameType(dst, src, dx, dy, sx, sy, w, h); }
template <typename T, int N>
static void blitSameType(const msdfgen::BitmapSection<T, N> &dst, const msdfgen::BitmapConstSection<T, N> &src, int dx, int dy, int sx, int sy, int w, int h) {
BOUND_SECTION();
size_t rowSize = sizeof(T)*N*w;
for (int y = 0; y < h; ++y)
memcpy(dst(dx, dy+y), src(sx, sy+y), rowSize);
}
#define BLIT_SAME_TYPE_IMPL(T, N) void blit(const msdfgen::BitmapSection<T, N> &dst, const msdfgen::BitmapConstSection<T, N> &src) { blitSameType(dst, src); }
#define BLIT_SAME_TYPE_PART_IMPL(T, N) void blit(const msdfgen::BitmapSection<T, N> &dst, const msdfgen::BitmapConstSection<T, N> &src, int dx, int dy, int sx, int sy, int w, int h) { blitSameType(dst, src, dx, dy, sx, sy, w, h); }
BLIT_SAME_TYPE_IMPL(byte, 1)
BLIT_SAME_TYPE_IMPL(byte, 3)
@@ -31,40 +41,83 @@ BLIT_SAME_TYPE_IMPL(float, 1)
BLIT_SAME_TYPE_IMPL(float, 3)
BLIT_SAME_TYPE_IMPL(float, 4)
void blit(const msdfgen::BitmapRef<byte, 1> &dst, const msdfgen::BitmapConstRef<float, 1> &src, int dx, int dy, int sx, int sy, int w, int h) {
BOUND_AREA();
for (int y = 0; y < h; ++y) {
byte *dstPixel = dst(dx, dy+y);
for (int x = 0; x < w; ++x) {
const float *srcPixel = src(sx+x, sy+y);
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel);
void blit(const msdfgen::BitmapSection<byte, 1> &dst, const msdfgen::BitmapConstSection<float, 1> &src) {
int width = std::min(dst.width, src.width), height = std::min(dst.height, src.height);
for (int y = 0; y < height; ++y) {
byte *dstPixel = dst(0, y);
const float *srcPixel = src(0, y);
for (int x = 0; x < width; ++x)
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
}
}
void blit(const msdfgen::BitmapSection<byte, 3> &dst, const msdfgen::BitmapConstSection<float, 3> &src) {
int width = std::min(dst.width, src.width), height = std::min(dst.height, src.height);
for (int y = 0; y < height; ++y) {
byte *dstPixel = dst(0, y);
const float *srcPixel = src(0, y);
for (int x = 0; x < width; ++x) {
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
}
}
}
void blit(const msdfgen::BitmapRef<byte, 3> &dst, const msdfgen::BitmapConstRef<float, 3> &src, int dx, int dy, int sx, int sy, int w, int h) {
BOUND_AREA();
for (int y = 0; y < h; ++y) {
byte *dstPixel = dst(dx, dy+y);
for (int x = 0; x < w; ++x) {
const float *srcPixel = src(sx+x, sy+y);
*dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[0]);
*dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[1]);
*dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[2]);
void blit(const msdfgen::BitmapSection<byte, 4> &dst, const msdfgen::BitmapConstSection<float, 4> &src) {
int width = std::min(dst.width, src.width), height = std::min(dst.height, src.height);
for (int y = 0; y < height; ++y) {
byte *dstPixel = dst(0, y);
const float *srcPixel = src(0, y);
for (int x = 0; x < width; ++x) {
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
}
}
}
void blit(const msdfgen::BitmapRef<byte, 4> &dst, const msdfgen::BitmapConstRef<float, 4> &src, int dx, int dy, int sx, int sy, int w, int h) {
BOUND_AREA();
BLIT_SAME_TYPE_PART_IMPL(byte, 1)
BLIT_SAME_TYPE_PART_IMPL(byte, 3)
BLIT_SAME_TYPE_PART_IMPL(byte, 4)
BLIT_SAME_TYPE_PART_IMPL(float, 1)
BLIT_SAME_TYPE_PART_IMPL(float, 3)
BLIT_SAME_TYPE_PART_IMPL(float, 4)
void blit(const msdfgen::BitmapSection<byte, 1> &dst, const msdfgen::BitmapConstSection<float, 1> &src, int dx, int dy, int sx, int sy, int w, int h) {
BOUND_SECTION();
for (int y = 0; y < h; ++y) {
byte *dstPixel = dst(dx, dy+y);
const float *srcPixel = src(sx, sy+y);
for (int x = 0; x < w; ++x)
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
}
}
void blit(const msdfgen::BitmapSection<byte, 3> &dst, const msdfgen::BitmapConstSection<float, 3> &src, int dx, int dy, int sx, int sy, int w, int h) {
BOUND_SECTION();
for (int y = 0; y < h; ++y) {
byte *dstPixel = dst(dx, dy+y);
const float *srcPixel = src(sx, sy+y);
for (int x = 0; x < w; ++x) {
const float *srcPixel = src(sx+x, sy+y);
*dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[0]);
*dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[1]);
*dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[2]);
*dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[3]);
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
}
}
}
void blit(const msdfgen::BitmapSection<byte, 4> &dst, const msdfgen::BitmapConstSection<float, 4> &src, int dx, int dy, int sx, int sy, int w, int h) {
BOUND_SECTION();
for (int y = 0; y < h; ++y) {
byte *dstPixel = dst(dx, dy+y);
const float *srcPixel = src(sx, sy+y);
for (int x = 0; x < w; ++x) {
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
*dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel++);
}
}
}

View File

@@ -8,18 +8,32 @@ namespace msdf_atlas {
/*
* Copies a rectangular section from source bitmap to destination bitmap.
* Makes sure not to access pixels outside either bitmap's bounds.
* The two bitmaps must not overlap.
*/
void blit(const msdfgen::BitmapRef<byte, 1> &dst, const msdfgen::BitmapConstRef<byte, 1> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapRef<byte, 3> &dst, const msdfgen::BitmapConstRef<byte, 3> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapRef<byte, 4> &dst, const msdfgen::BitmapConstRef<byte, 4> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapSection<byte, 1> &dst, const msdfgen::BitmapConstSection<byte, 1> &src);
void blit(const msdfgen::BitmapSection<byte, 3> &dst, const msdfgen::BitmapConstSection<byte, 3> &src);
void blit(const msdfgen::BitmapSection<byte, 4> &dst, const msdfgen::BitmapConstSection<byte, 4> &src);
void blit(const msdfgen::BitmapRef<float, 1> &dst, const msdfgen::BitmapConstRef<float, 1> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapRef<float, 3> &dst, const msdfgen::BitmapConstRef<float, 3> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapRef<float, 4> &dst, const msdfgen::BitmapConstRef<float, 4> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapSection<float, 1> &dst, const msdfgen::BitmapConstSection<float, 1> &src);
void blit(const msdfgen::BitmapSection<float, 3> &dst, const msdfgen::BitmapConstSection<float, 3> &src);
void blit(const msdfgen::BitmapSection<float, 4> &dst, const msdfgen::BitmapConstSection<float, 4> &src);
void blit(const msdfgen::BitmapRef<byte, 1> &dst, const msdfgen::BitmapConstRef<float, 1> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapRef<byte, 3> &dst, const msdfgen::BitmapConstRef<float, 3> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapRef<byte, 4> &dst, const msdfgen::BitmapConstRef<float, 4> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapSection<byte, 1> &dst, const msdfgen::BitmapConstSection<float, 1> &src);
void blit(const msdfgen::BitmapSection<byte, 3> &dst, const msdfgen::BitmapConstSection<float, 3> &src);
void blit(const msdfgen::BitmapSection<byte, 4> &dst, const msdfgen::BitmapConstSection<float, 4> &src);
void blit(const msdfgen::BitmapSection<byte, 1> &dst, const msdfgen::BitmapConstSection<byte, 1> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapSection<byte, 3> &dst, const msdfgen::BitmapConstSection<byte, 3> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapSection<byte, 4> &dst, const msdfgen::BitmapConstSection<byte, 4> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapSection<float, 1> &dst, const msdfgen::BitmapConstSection<float, 1> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapSection<float, 3> &dst, const msdfgen::BitmapConstSection<float, 3> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapSection<float, 4> &dst, const msdfgen::BitmapConstSection<float, 4> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapSection<byte, 1> &dst, const msdfgen::BitmapConstSection<float, 1> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapSection<byte, 3> &dst, const msdfgen::BitmapConstSection<float, 3> &src, int dx, int dy, int sx, int sy, int w, int h);
void blit(const msdfgen::BitmapSection<byte, 4> &dst, const msdfgen::BitmapConstSection<float, 4> &src, int dx, int dy, int sx, int sy, int w, int h);
}

View File

@@ -6,7 +6,7 @@
namespace msdf_atlas {
bool exportCSV(const FontGeometry *fonts, int fontCount, int atlasWidth, int atlasHeight, YDirection yDirection, const char *filename) {
bool exportCSV(const FontGeometry *fonts, int fontCount, int atlasWidth, int atlasHeight, msdfgen::YAxisOrientation yDirection, const char *filename) {
FILE *f = fopen(filename, "w");
if (!f)
return false;
@@ -19,19 +19,19 @@ bool exportCSV(const FontGeometry *fonts, int fontCount, int atlasWidth, int atl
fprintf(f, "%d,%.17g,", glyph.getIdentifier(fonts[i].getPreferredIdentifierType()), glyph.getAdvance());
glyph.getQuadPlaneBounds(l, b, r, t);
switch (yDirection) {
case YDirection::BOTTOM_UP:
case msdfgen::Y_UPWARD:
fprintf(f, "%.17g,%.17g,%.17g,%.17g,", l, b, r, t);
break;
case YDirection::TOP_DOWN:
case msdfgen::Y_DOWNWARD:
fprintf(f, "%.17g,%.17g,%.17g,%.17g,", l, -t, r, -b);
break;
}
glyph.getQuadAtlasBounds(l, b, r, t);
switch (yDirection) {
case YDirection::BOTTOM_UP:
case msdfgen::Y_UPWARD:
fprintf(f, "%.17g,%.17g,%.17g,%.17g\n", l, b, r, t);
break;
case YDirection::TOP_DOWN:
case msdfgen::Y_DOWNWARD:
fprintf(f, "%.17g,%.17g,%.17g,%.17g\n", l, atlasHeight-t, r, atlasHeight-b);
break;
}

View File

@@ -9,6 +9,6 @@ namespace msdf_atlas {
* Writes the positioning data and atlas layout of the glyphs into a CSV file
* The columns are: font variant index (if fontCount > 1), glyph identifier (index or Unicode), horizontal advance, plane bounds (l, b, r, t), atlas bounds (l, b, r, t)
*/
bool exportCSV(const FontGeometry *fonts, int fontCount, int atlasWidth, int atlasHeight, YDirection yDirection, const char *filename);
bool exportCSV(const FontGeometry *fonts, int fontCount, int atlasWidth, int atlasHeight, msdfgen::YAxisOrientation yDirection, const char *filename);
}

View File

@@ -3,23 +3,23 @@
namespace msdf_atlas {
void scanlineGenerator(const msdfgen::BitmapRef<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
void scanlineGenerator(const msdfgen::BitmapSection<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
msdfgen::rasterize(output, glyph.getShape(), glyph.getBoxScale(), glyph.getBoxTranslate(), MSDF_ATLAS_GLYPH_FILL_RULE);
}
void sdfGenerator(const msdfgen::BitmapRef<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
void sdfGenerator(const msdfgen::BitmapSection<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
msdfgen::generateSDF(output, glyph.getShape(), glyph.getBoxProjection(), glyph.getBoxRange(), attribs.config);
if (attribs.scanlinePass)
msdfgen::distanceSignCorrection(output, glyph.getShape(), glyph.getBoxProjection(), MSDF_ATLAS_GLYPH_FILL_RULE);
}
void psdfGenerator(const msdfgen::BitmapRef<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
void psdfGenerator(const msdfgen::BitmapSection<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
msdfgen::generatePSDF(output, glyph.getShape(), glyph.getBoxProjection(), glyph.getBoxRange(), attribs.config);
if (attribs.scanlinePass)
msdfgen::distanceSignCorrection(output, glyph.getShape(), glyph.getBoxProjection(), MSDF_ATLAS_GLYPH_FILL_RULE);
}
void msdfGenerator(const msdfgen::BitmapRef<float, 3> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
void msdfGenerator(const msdfgen::BitmapSection<float, 3> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
msdfgen::MSDFGeneratorConfig config = attribs.config;
if (attribs.scanlinePass)
config.errorCorrection.mode = msdfgen::ErrorCorrectionConfig::DISABLED;
@@ -34,7 +34,7 @@ void msdfGenerator(const msdfgen::BitmapRef<float, 3> &output, const GlyphGeomet
}
}
void mtsdfGenerator(const msdfgen::BitmapRef<float, 4> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
void mtsdfGenerator(const msdfgen::BitmapSection<float, 4> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
msdfgen::MSDFGeneratorConfig config = attribs.config;
if (attribs.scanlinePass)
config.errorCorrection.mode = msdfgen::ErrorCorrectionConfig::DISABLED;

View File

@@ -12,14 +12,14 @@ namespace msdf_atlas {
// Glyph bitmap generator functions
/// Generates non-anti-aliased binary image of the glyph using scanline rasterization
void scanlineGenerator(const msdfgen::BitmapRef<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs);
void scanlineGenerator(const msdfgen::BitmapSection<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs);
/// Generates a true signed distance field of the glyph
void sdfGenerator(const msdfgen::BitmapRef<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs);
void sdfGenerator(const msdfgen::BitmapSection<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs);
/// Generates a signed perpendicular distance field of the glyph
void psdfGenerator(const msdfgen::BitmapRef<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs);
void psdfGenerator(const msdfgen::BitmapSection<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs);
/// Generates a multi-channel signed distance field of the glyph
void msdfGenerator(const msdfgen::BitmapRef<float, 3> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs);
void msdfGenerator(const msdfgen::BitmapSection<float, 3> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs);
/// Generates a multi-channel and alpha-encoded true signed distance field of the glyph
void mtsdfGenerator(const msdfgen::BitmapRef<float, 4> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs);
void mtsdfGenerator(const msdfgen::BitmapSection<float, 4> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs);
}

View File

@@ -30,7 +30,7 @@ static void pngWrite(png_structp png, png_bytep data, png_size_t length) {
static void pngFlush(png_structp) { }
static bool pngEncode(std::vector<byte> &output, const byte *pixels, int width, int height, int channels, int colorType) {
static bool pngEncode(std::vector<byte> &output, const byte *pixels, int width, int height, int rowStride, int colorType) {
if (!(pixels && width && height))
return false;
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &pngIgnoreError, &pngIgnoreError);
@@ -42,7 +42,7 @@ static bool pngEncode(std::vector<byte> &output, const byte *pixels, int width,
return false;
std::vector<const byte *> rows(height);
for (int y = 0; y < height; ++y)
rows[y] = pixels+channels*width*(height-y-1);
rows[y] = pixels+rowStride*y;
if (setjmp(png_jmpbuf(png)))
return false;
png_set_write_fn(png, &output, &pngWrite, &pngFlush);
@@ -53,38 +53,48 @@ static bool pngEncode(std::vector<byte> &output, const byte *pixels, int width,
return true;
}
static bool pngEncode(std::vector<byte> &output, const float *pixels, int width, int height, int channels, int colorType) {
static bool pngEncode(std::vector<byte> &output, const float *pixels, int width, int height, int rowStride, int channels, int colorType) {
if (!(pixels && width && height))
return false;
int subpixels = channels*width*height;
std::vector<byte> bytePixels(subpixels);
for (int i = 0; i < subpixels; ++i)
bytePixels[i] = msdfgen::pixelFloatToByte(pixels[i]);
return pngEncode(output, bytePixels.data(), width, height, channels, colorType);
std::vector<byte> bytePixels(channels*width*height);
byte *dst = bytePixels.data();
const float *rowStart = pixels;
for (int y = 0; y < height; ++y) {
for (const float *src = rowStart, *end = rowStart+channels*width; src < end; ++src)
*dst++ = msdfgen::pixelFloatToByte(*src);
rowStart += rowStride;
}
return pngEncode(output, bytePixels.data(), width, height, channels*width, colorType);
}
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<msdfgen::byte, 1> &bitmap) {
return pngEncode(output, bitmap.pixels, bitmap.width, bitmap.height, 1, PNG_COLOR_TYPE_GRAY);
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<byte, 1> bitmap) {
bitmap.reorient(msdfgen::Y_DOWNWARD);
return pngEncode(output, bitmap.pixels, bitmap.width, bitmap.height, bitmap.rowStride, PNG_COLOR_TYPE_GRAY);
}
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<msdfgen::byte, 3> &bitmap) {
return pngEncode(output, bitmap.pixels, bitmap.width, bitmap.height, 3, PNG_COLOR_TYPE_RGB);
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<byte, 3> bitmap) {
bitmap.reorient(msdfgen::Y_DOWNWARD);
return pngEncode(output, bitmap.pixels, bitmap.width, bitmap.height, bitmap.rowStride, PNG_COLOR_TYPE_RGB);
}
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<msdfgen::byte, 4> &bitmap) {
return pngEncode(output, bitmap.pixels, bitmap.width, bitmap.height, 4, PNG_COLOR_TYPE_RGB_ALPHA);
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<byte, 4> bitmap) {
bitmap.reorient(msdfgen::Y_DOWNWARD);
return pngEncode(output, bitmap.pixels, bitmap.width, bitmap.height, bitmap.rowStride, PNG_COLOR_TYPE_RGB_ALPHA);
}
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<float, 1> &bitmap) {
return pngEncode(output, bitmap.pixels, bitmap.width, bitmap.height, 1, PNG_COLOR_TYPE_GRAY);
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<float, 1> bitmap) {
bitmap.reorient(msdfgen::Y_DOWNWARD);
return pngEncode(output, bitmap.pixels, bitmap.width, bitmap.height, bitmap.rowStride, 1, PNG_COLOR_TYPE_GRAY);
}
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<float, 3> &bitmap) {
return pngEncode(output, bitmap.pixels, bitmap.width, bitmap.height, 3, PNG_COLOR_TYPE_RGB);
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<float, 3> bitmap) {
bitmap.reorient(msdfgen::Y_DOWNWARD);
return pngEncode(output, bitmap.pixels, bitmap.width, bitmap.height, bitmap.rowStride, 3, PNG_COLOR_TYPE_RGB);
}
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<float, 4> &bitmap) {
return pngEncode(output, bitmap.pixels, bitmap.width, bitmap.height, 4, PNG_COLOR_TYPE_RGB_ALPHA);
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<float, 4> bitmap) {
bitmap.reorient(msdfgen::Y_DOWNWARD);
return pngEncode(output, bitmap.pixels, bitmap.width, bitmap.height, bitmap.rowStride, 4, PNG_COLOR_TYPE_RGB_ALPHA);
}
}
@@ -97,58 +107,67 @@ bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<float, 4
namespace msdf_atlas {
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<msdfgen::byte, 1> &bitmap) {
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<byte, 1> bitmap) {
std::vector<byte> pixels(bitmap.width*bitmap.height);
bitmap.reorient(msdfgen::Y_DOWNWARD);
for (int y = 0; y < bitmap.height; ++y)
memcpy(&pixels[bitmap.width*y], bitmap(0, bitmap.height-y-1), bitmap.width);
memcpy(&pixels[bitmap.width*y], bitmap(0, y), bitmap.width);
return !lodepng::encode(output, pixels, bitmap.width, bitmap.height, LCT_GREY);
}
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<msdfgen::byte, 3> &bitmap) {
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<byte, 3> bitmap) {
std::vector<byte> pixels(3*bitmap.width*bitmap.height);
bitmap.reorient(msdfgen::Y_DOWNWARD);
for (int y = 0; y < bitmap.height; ++y)
memcpy(&pixels[3*bitmap.width*y], bitmap(0, bitmap.height-y-1), 3*bitmap.width);
memcpy(&pixels[3*bitmap.width*y], bitmap(0, y), 3*bitmap.width);
return !lodepng::encode(output, pixels, bitmap.width, bitmap.height, LCT_RGB);
}
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<msdfgen::byte, 4> &bitmap) {
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<byte, 4> bitmap) {
std::vector<byte> pixels(4*bitmap.width*bitmap.height);
bitmap.reorient(msdfgen::Y_DOWNWARD);
for (int y = 0; y < bitmap.height; ++y)
memcpy(&pixels[4*bitmap.width*y], bitmap(0, bitmap.height-y-1), 4*bitmap.width);
memcpy(&pixels[4*bitmap.width*y], bitmap(0, y), 4*bitmap.width);
return !lodepng::encode(output, pixels, bitmap.width, bitmap.height, LCT_RGBA);
}
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<float, 1> &bitmap) {
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<float, 1> bitmap) {
std::vector<byte> pixels(bitmap.width*bitmap.height);
std::vector<byte>::iterator it = pixels.begin();
for (int y = bitmap.height-1; y >= 0; --y)
bitmap.reorient(msdfgen::Y_DOWNWARD);
for (int y = 0; y < bitmap.height; ++y) {
for (int x = 0; x < bitmap.width; ++x)
*it++ = msdfgen::pixelFloatToByte(*bitmap(x, y));
}
return !lodepng::encode(output, pixels, bitmap.width, bitmap.height, LCT_GREY);
}
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<float, 3> &bitmap) {
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<float, 3> bitmap) {
std::vector<byte> pixels(3*bitmap.width*bitmap.height);
std::vector<byte>::iterator it = pixels.begin();
for (int y = bitmap.height-1; y >= 0; --y)
bitmap.reorient(msdfgen::Y_DOWNWARD);
for (int y = 0; y < bitmap.height; ++y) {
for (int x = 0; x < bitmap.width; ++x) {
*it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[0]);
*it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[1]);
*it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[2]);
}
}
return !lodepng::encode(output, pixels, bitmap.width, bitmap.height, LCT_RGB);
}
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<float, 4> &bitmap) {
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<float, 4> bitmap) {
std::vector<byte> pixels(4*bitmap.width*bitmap.height);
std::vector<byte>::iterator it = pixels.begin();
for (int y = bitmap.height-1; y >= 0; --y)
bitmap.reorient(msdfgen::Y_DOWNWARD);
for (int y = 0; y < bitmap.height; ++y) {
for (int x = 0; x < bitmap.width; ++x) {
*it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[0]);
*it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[1]);
*it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[2]);
*it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[3]);
}
}
return !lodepng::encode(output, pixels, bitmap.width, bitmap.height, LCT_RGBA);
}

View File

@@ -12,12 +12,12 @@ namespace msdf_atlas {
// Functions to encode an image as a sequence of bytes in memory
// Only PNG format available currently
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<msdfgen::byte, 1> &bitmap);
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<msdfgen::byte, 3> &bitmap);
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<msdfgen::byte, 4> &bitmap);
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<float, 1> &bitmap);
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<float, 3> &bitmap);
bool encodePng(std::vector<byte> &output, const msdfgen::BitmapConstRef<float, 4> &bitmap);
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<byte, 1> bitmap);
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<byte, 3> bitmap);
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<byte, 4> bitmap);
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<float, 1> bitmap);
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<float, 3> bitmap);
bool encodePng(std::vector<byte> &output, msdfgen::BitmapConstSection<float, 4> bitmap);
}

View File

@@ -8,7 +8,7 @@ namespace msdf_atlas {
/// Saves the bitmap as an image file with the specified format
template <typename T, int N>
bool saveImage(const msdfgen::BitmapConstRef<T, N> &bitmap, ImageFormat format, const char *filename, YDirection outputYDirection = YDirection::BOTTOM_UP);
bool saveImage(const msdfgen::BitmapConstSection<T, N> &bitmap, ImageFormat format, const char *filename);
}

View File

@@ -7,19 +7,19 @@
namespace msdf_atlas {
template <int N>
bool saveImageBinary(const msdfgen::BitmapConstRef<byte, N> &bitmap, const char *filename, YDirection outputYDirection);
bool saveImageBinary(msdfgen::BitmapConstSection<byte, N> bitmap, const char *filename);
template <int N>
bool saveImageBinaryLE(const msdfgen::BitmapConstRef<float, N> &bitmap, const char *filename, YDirection outputYDirection);
bool saveImageBinaryLE(msdfgen::BitmapConstSection<float, N> bitmap, const char *filename);
template <int N>
bool saveImageBinaryBE(const msdfgen::BitmapConstRef<float, N> &bitmap, const char *filename, YDirection outputYDirection);
bool saveImageBinaryBE(msdfgen::BitmapConstSection<float, N> bitmap, const char *filename);
template <int N>
bool saveImageText(const msdfgen::BitmapConstRef<byte, N> &bitmap, const char *filename, YDirection outputYDirection);
bool saveImageText(msdfgen::BitmapConstSection<byte, N> bitmap, const char *filename);
template <int N>
bool saveImageText(const msdfgen::BitmapConstRef<float, N> &bitmap, const char *filename, YDirection outputYDirection);
bool saveImageText(msdfgen::BitmapConstSection<float, N> bitmap, const char *filename);
template <int N>
bool saveImage(const msdfgen::BitmapConstRef<byte, N> &bitmap, ImageFormat format, const char *filename, YDirection outputYDirection = YDirection::BOTTOM_UP) {
bool saveImage(const msdfgen::BitmapConstSection<byte, N> &bitmap, ImageFormat format, const char *filename) {
switch (format) {
#ifndef MSDFGEN_DISABLE_PNG
case ImageFormat::PNG:
@@ -34,11 +34,11 @@ bool saveImage(const msdfgen::BitmapConstRef<byte, N> &bitmap, ImageFormat forma
case ImageFormat::FL32:
return false;
case ImageFormat::TEXT:
return saveImageText(bitmap, filename, outputYDirection);
return saveImageText(bitmap, filename);
case ImageFormat::TEXT_FLOAT:
return false;
case ImageFormat::BINARY:
return saveImageBinary(bitmap, filename, outputYDirection);
return saveImageBinary(bitmap, filename);
case ImageFormat::BINARY_FLOAT:
case ImageFormat::BINARY_FLOAT_BE:
return false;
@@ -48,7 +48,7 @@ bool saveImage(const msdfgen::BitmapConstRef<byte, N> &bitmap, ImageFormat forma
}
template <int N>
bool saveImage(const msdfgen::BitmapConstRef<float, N> &bitmap, ImageFormat format, const char *filename, YDirection outputYDirection = YDirection::BOTTOM_UP) {
bool saveImage(const msdfgen::BitmapConstSection<float, N> &bitmap, ImageFormat format, const char *filename) {
switch (format) {
#ifndef MSDFGEN_DISABLE_PNG
case ImageFormat::PNG:
@@ -61,36 +61,29 @@ bool saveImage(const msdfgen::BitmapConstRef<float, N> &bitmap, ImageFormat form
case ImageFormat::RGBA:
return msdfgen::saveRgba(bitmap, filename);
case ImageFormat::FL32:
return msdfgen::saveFl32(msdfgen::BitmapConstSection<float, N>(bitmap), filename);
return msdfgen::saveFl32(bitmap, filename);
case ImageFormat::TEXT:
return false;
case ImageFormat::TEXT_FLOAT:
return saveImageText(bitmap, filename, outputYDirection);
return saveImageText(bitmap, filename);
case ImageFormat::BINARY:
return false;
case ImageFormat::BINARY_FLOAT:
return saveImageBinaryLE(bitmap, filename, outputYDirection);
return saveImageBinaryLE(bitmap, filename);
case ImageFormat::BINARY_FLOAT_BE:
return saveImageBinaryBE(bitmap, filename, outputYDirection);
return saveImageBinaryBE(bitmap, filename);
default:;
}
return false;
}
template <int N>
bool saveImageBinary(const msdfgen::BitmapConstRef<byte, N> &bitmap, const char *filename, YDirection outputYDirection) {
bool saveImageBinary(msdfgen::BitmapConstSection<byte, N> bitmap, const char *filename) {
bool success = false;
if (FILE *f = fopen(filename, "wb")) {
size_t written = 0;
switch (outputYDirection) {
case YDirection::BOTTOM_UP:
written = fwrite(bitmap.pixels, 1, (size_t) N*bitmap.width*bitmap.height, f);
break;
case YDirection::TOP_DOWN:
for (int y = bitmap.height-1; y >= 0; --y)
written += fwrite(bitmap.pixels+(size_t) N*bitmap.width*y, 1, (size_t) N*bitmap.width, f);
break;
}
for (int y = 0; y < bitmap.height; ++y)
written += fwrite(bitmap(0, y), 1, (size_t) N*bitmap.width, f);
success = written == (size_t) N*bitmap.width*bitmap.height;
fclose(f);
}
@@ -104,19 +97,13 @@ bool
#else
saveImageBinaryLE
#endif
(const msdfgen::BitmapConstRef<float, N> &bitmap, const char *filename, YDirection outputYDirection) {
(msdfgen::BitmapConstSection<float, N> bitmap, const char *filename)
{
bool success = false;
if (FILE *f = fopen(filename, "wb")) {
size_t written = 0;
switch (outputYDirection) {
case YDirection::BOTTOM_UP:
written = fwrite(bitmap.pixels, sizeof(float), (size_t) N*bitmap.width*bitmap.height, f);
break;
case YDirection::TOP_DOWN:
for (int y = bitmap.height-1; y >= 0; --y)
written += fwrite(bitmap.pixels+(size_t) N*bitmap.width*y, sizeof(float), (size_t) N*bitmap.width, f);
break;
}
for (int y = 0; y < bitmap.height; ++y)
written += fwrite(bitmap(0, y), sizeof(float), (size_t) N*bitmap.width, f);
success = written == (size_t) N*bitmap.width*bitmap.height;
fclose(f);
}
@@ -130,12 +117,13 @@ bool
#else
saveImageBinaryBE
#endif
(const msdfgen::BitmapConstRef<float, N> &bitmap, const char *filename, YDirection outputYDirection) {
(msdfgen::BitmapConstSection<float, N> bitmap, const char *filename)
{
bool success = false;
if (FILE *f = fopen(filename, "wb")) {
size_t written = 0;
for (int y = 0; y < bitmap.height; ++y) {
const float *p = bitmap.pixels+(size_t) N*bitmap.width*(outputYDirection == YDirection::TOP_DOWN ? bitmap.height-y-1 : y);
const float *p = bitmap(0, y);
for (int x = 0; x < bitmap.width; ++x) {
const unsigned char *b = reinterpret_cast<const unsigned char *>(p++);
for (int i = sizeof(float)-1; i >= 0; --i)
@@ -150,12 +138,12 @@ bool
template <int N>
bool saveImageText(const msdfgen::BitmapConstRef<byte, N> &bitmap, const char *filename, YDirection outputYDirection) {
bool saveImageText(msdfgen::BitmapConstSection<byte, N> bitmap, const char *filename) {
bool success = false;
if (FILE *f = fopen(filename, "wb")) {
success = true;
for (int y = 0; y < bitmap.height; ++y) {
const byte *p = bitmap.pixels+(size_t) N*bitmap.width*(outputYDirection == YDirection::TOP_DOWN ? bitmap.height-y-1 : y);
const byte *p = bitmap(0, y);
for (int x = 0; x < N*bitmap.width; ++x)
success &= fprintf(f, x ? " %02X" : "%02X", (unsigned) *p++) > 0;
success &= fprintf(f, "\n") > 0;
@@ -166,12 +154,12 @@ bool saveImageText(const msdfgen::BitmapConstRef<byte, N> &bitmap, const char *f
}
template <int N>
bool saveImageText(const msdfgen::BitmapConstRef<float, N> &bitmap, const char *filename, YDirection outputYDirection) {
bool saveImageText(msdfgen::BitmapConstSection<float, N> bitmap, const char *filename) {
bool success = false;
if (FILE *f = fopen(filename, "wb")) {
success = true;
for (int y = 0; y < bitmap.height; ++y) {
const float *p = bitmap.pixels+(size_t) N*bitmap.width*(outputYDirection == YDirection::TOP_DOWN ? bitmap.height-y-1 : y);
const float *p = bitmap(0, y);
for (int x = 0; x < N*bitmap.width; ++x)
success &= fprintf(f, x ? " %g" : "%g", *p++) > 0;
success &= fprintf(f, "\n") > 0;

View File

@@ -74,7 +74,7 @@ bool exportJSON(const FontGeometry *fonts, int fontCount, ImageType imageType, c
fprintf(f, "\"size\":%.17g,", metrics.size);
fprintf(f, "\"width\":%d,", metrics.width);
fprintf(f, "\"height\":%d,", metrics.height);
fprintf(f, "\"yOrigin\":\"%s\"", metrics.yDirection == YDirection::TOP_DOWN ? "top" : "bottom");
fprintf(f, "\"yOrigin\":\"%s\"", metrics.yDirection == msdfgen::Y_DOWNWARD ? "top" : "bottom");
if (metrics.grid) {
fputs(",\"grid\":{", f);
fprintf(f, "\"cellWidth\":%d,", metrics.grid->cellWidth);
@@ -85,10 +85,10 @@ bool exportJSON(const FontGeometry *fonts, int fontCount, ImageType imageType, c
fprintf(f, ",\"originX\":%.17g", *metrics.grid->originX);
if (metrics.grid->originY) {
switch (metrics.yDirection) {
case YDirection::BOTTOM_UP:
case msdfgen::Y_UPWARD:
fprintf(f, ",\"originY\":%.17g", *metrics.grid->originY);
break;
case YDirection::TOP_DOWN:
case msdfgen::Y_DOWNWARD:
fprintf(f, ",\"originY\":%.17g", (metrics.grid->cellHeight-metrics.grid->spacing-1)/metrics.size-*metrics.grid->originY);
break;
}
@@ -111,7 +111,7 @@ bool exportJSON(const FontGeometry *fonts, int fontCount, ImageType imageType, c
// Font metrics
fputs("\"metrics\":{", f); {
double yFactor = metrics.yDirection == YDirection::TOP_DOWN ? -1 : 1;
double yFactor = metrics.yDirection == msdfgen::Y_DOWNWARD ? -1 : 1;
const msdfgen::FontMetrics &fontMetrics = font.getMetrics();
fprintf(f, "\"emSize\":%.17g,", fontMetrics.emSize);
fprintf(f, "\"lineHeight\":%.17g,", fontMetrics.lineHeight);
@@ -139,10 +139,10 @@ bool exportJSON(const FontGeometry *fonts, int fontCount, ImageType imageType, c
glyph.getQuadPlaneBounds(l, b, r, t);
if (l || b || r || t) {
switch (metrics.yDirection) {
case YDirection::BOTTOM_UP:
case msdfgen::Y_UPWARD:
fprintf(f, ",\"planeBounds\":{\"left\":%.17g,\"bottom\":%.17g,\"right\":%.17g,\"top\":%.17g}", l, b, r, t);
break;
case YDirection::TOP_DOWN:
case msdfgen::Y_DOWNWARD:
fprintf(f, ",\"planeBounds\":{\"left\":%.17g,\"top\":%.17g,\"right\":%.17g,\"bottom\":%.17g}", l, -t, r, -b);
break;
}
@@ -150,10 +150,10 @@ bool exportJSON(const FontGeometry *fonts, int fontCount, ImageType imageType, c
glyph.getQuadAtlasBounds(l, b, r, t);
if (l || b || r || t) {
switch (metrics.yDirection) {
case YDirection::BOTTOM_UP:
case msdfgen::Y_UPWARD:
fprintf(f, ",\"atlasBounds\":{\"left\":%.17g,\"bottom\":%.17g,\"right\":%.17g,\"top\":%.17g}", l, b, r, t);
break;
case YDirection::TOP_DOWN:
case msdfgen::Y_DOWNWARD:
fprintf(f, ",\"atlasBounds\":{\"left\":%.17g,\"top\":%.17g,\"right\":%.17g,\"bottom\":%.17g}", l, metrics.height-t, r, metrics.height-b);
break;
}

View File

@@ -18,7 +18,7 @@ struct JsonAtlasMetrics {
msdfgen::Range distanceRange;
double size;
int width, height;
YDirection yDirection;
msdfgen::YAxisOrientation yDirection;
const GridMetrics *grid;
};

View File

@@ -302,7 +302,7 @@ struct FontInput {
struct Configuration {
ImageType imageType;
ImageFormat imageFormat;
YDirection yDirection;
msdfgen::YAxisOrientation yDirection;
int width, height;
double emSize;
msdfgen::Range pxRange;
@@ -335,12 +335,13 @@ static bool makeAtlas(const std::vector<GlyphGeometry> &glyphs, const std::vecto
generator.setAttributes(config.generatorAttributes);
generator.setThreadCount(config.threadCount);
generator.generate(glyphs.data(), glyphs.size());
msdfgen::BitmapConstRef<T, N> bitmap = (msdfgen::BitmapConstRef<T, N>) generator.atlasStorage();
msdfgen::BitmapConstSection<T, N> bitmap = (msdfgen::BitmapConstSection<T, N>) generator.atlasStorage();
bitmap.reorient(config.yDirection);
bool success = true;
if (config.imageFilename) {
if (saveImage(bitmap, config.imageFormat, config.imageFilename, config.yDirection))
if (saveImage(bitmap, config.imageFormat, config.imageFilename))
fputs("Atlas image file saved.\n", stderr);
else {
success = false;
@@ -355,7 +356,6 @@ static bool makeAtlas(const std::vector<GlyphGeometry> &glyphs, const std::vecto
arfontProps.pxRange = config.pxRange;
arfontProps.imageType = config.imageType;
arfontProps.imageFormat = config.imageFormat;
arfontProps.yDirection = config.yDirection;
if (exportArteryFont<float>(fonts.data(), fonts.size(), bitmap, config.arteryFontFilename, arfontProps))
fputs("Artery Font file generated.\n", stderr);
else {
@@ -379,7 +379,7 @@ int main(int argc, const char *const *argv) {
fontInput.fontScale = -1;
config.imageType = ImageType::MSDF;
config.imageFormat = ImageFormat::UNSPECIFIED;
config.yDirection = YDirection::BOTTOM_UP;
config.yDirection = msdfgen::Y_UPWARD;
config.grid.fixedOriginX = false, config.grid.fixedOriginY = true;
config.edgeColoring = msdfgen::edgeColoringInkTrap;
config.kerning = true;
@@ -597,9 +597,9 @@ int main(int argc, const char *const *argv) {
}
ARG_CASE("-yorigin", 1) {
if (ARG_IS("bottom"))
config.yDirection = YDirection::BOTTOM_UP;
config.yDirection = msdfgen::Y_UPWARD;
else if (ARG_IS("top"))
config.yDirection = YDirection::TOP_DOWN;
config.yDirection = msdfgen::Y_DOWNWARD;
else
ABORT("Invalid Y-axis origin. Use bottom or top.");
++argPos;
@@ -1310,10 +1310,10 @@ int main(int argc, const char *const *argv) {
printf(", ");
if (config.grid.fixedOriginY) {
switch (config.yDirection) {
case YDirection::BOTTOM_UP:
case msdfgen::Y_UPWARD:
printf("Y = %.9g", uniformOriginY);
break;
case YDirection::TOP_DOWN:
case msdfgen::Y_DOWNWARD:
printf("Y = %.9g", (config.grid.cellHeight-spacing-1)/config.emSize-uniformOriginY);
break;
}

View File

@@ -8,7 +8,7 @@ namespace msdf_atlas {
static const char *const shadronFillGlyphMask = R"(
template <ATLAS, RANGE, ZERO_DIST, COLOR>
glsl vec4 fillGlyph(vec2 texCoord) {
vec4 fillGlyph(vec2 texCoord) {
float fill = texture((ATLAS), texCoord).r;
return vec4(vec3(COLOR), fill);
}
@@ -16,24 +16,25 @@ glsl vec4 fillGlyph(vec2 texCoord) {
static const char *const shadronFillGlyphSdf = R"(
template <ATLAS, RANGE, ZERO_DIST, COLOR>
glsl vec4 fillGlyph(vec2 texCoord) {
vec4 fillGlyph(vec2 texCoord) {
vec3 s = texture((ATLAS), texCoord).rgb;
float sd = dot(vec2(RANGE), 0.5/fwidth(texCoord))*(median(s.r, s.g, s.b)-ZERO_DIST);
float sd = 0.5*dot(vec2(RANGE), inversesqrt(sqr(dFdx(texCoord))+sqr(dFdy(texCoord))))*(median(s)-ZERO_DIST);
float fill = clamp(sd+0.5, 0.0, 1.0);
return vec4(vec3(COLOR), fill);
}
)";
static const char *const shadronPreviewPreamble = R"(
#include <sqr>
#include <median>
glsl struct GlyphVertex {
struct GlyphVertex {
vec2 coord;
vec2 texCoord;
};
template <TEXT_SIZE>
glsl vec4 projectVertex(out vec2 texCoord, in GlyphVertex vertex) {
vec4 projectVertex(out vec2 texCoord, in GlyphVertex vertex) {
vec2 coord = vertex.coord;
float scale = 2.0/max((TEXT_SIZE).x, shadron_Aspect*(TEXT_SIZE).y);
scale *= exp(0.0625*shadron_Mouse.z);
@@ -44,8 +45,6 @@ glsl vec4 projectVertex(out vec2 texCoord, in GlyphVertex vertex) {
}
%s
#define PREVIEW_IMAGE(NAME, ATLAS, RANGE, ZERO_DIST, COLOR, VERTEX_LIST, TEXT_SIZE, DIMENSIONS) model image NAME : \
vertex_data(GlyphVertex), \
fragment_data(vec2), \
vertex(projectVertex<TEXT_SIZE>, triangles, VERTEX_LIST), \
fragment(fillGlyph<ATLAS, RANGE, ZERO_DIST, COLOR>), \
depth(false), \

View File

@@ -45,12 +45,6 @@ enum class GlyphIdentifierType {
UNICODE_CODEPOINT
};
/// Direction of the Y-axis
enum class YDirection {
BOTTOM_UP,
TOP_DOWN
};
/// The method of computing the layout of the atlas
enum class PackingStyle {
TIGHT,