Overlapped atlas storage and EC testing
This commit is contained in:
parent
c27de5988d
commit
c4e45732ce
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "AtlasStorage.h"
|
||||
|
||||
namespace msdf_atlas {
|
||||
|
||||
/** An implementation of AtlasStorage represented by a bitmap in memory (msdfgen::Bitmap)
|
||||
* which has improved handling of partially overlapping glyph rectangles
|
||||
*/
|
||||
template <typename T, int N>
|
||||
class BitmapOverlappedAtlasStorage {
|
||||
|
||||
public:
|
||||
BitmapOverlappedAtlasStorage();
|
||||
BitmapOverlappedAtlasStorage(int width, int height);
|
||||
BitmapOverlappedAtlasStorage(const BitmapOverlappedAtlasStorage<T, N> &orig, int width, int height);
|
||||
operator msdfgen::BitmapConstRef<T, N>() const;
|
||||
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;
|
||||
|
||||
private:
|
||||
msdfgen::Bitmap<T, N> bitmap;
|
||||
msdfgen::Bitmap<byte, 1> stencil;
|
||||
|
||||
void blend(const msdfgen::BitmapRef<byte, N> &dst, const msdfgen::BitmapConstRef<byte, N> &src, int dx, int dy, int sx, int sy, int w, int h);
|
||||
void blend(const msdfgen::BitmapRef<byte, N> &dst, const msdfgen::BitmapConstRef<float, N> &src, int dx, int dy, int sx, int sy, int w, int h);
|
||||
void blend(const msdfgen::BitmapRef<float, N> &dst, const msdfgen::BitmapConstRef<float, N> &src, int dx, int dy, int sx, int sy, int w, int h);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include "BitmapOverlappedAtlasStorage.hpp"
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
|
||||
#include "BitmapOverlappedAtlasStorage.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include "bitmap-blit.h"
|
||||
|
||||
namespace msdf_atlas {
|
||||
|
||||
template <typename T>
|
||||
T minPxVal();
|
||||
|
||||
template <>
|
||||
byte minPxVal() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
float minPxVal() {
|
||||
return -FLT_MAX;
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
BitmapOverlappedAtlasStorage<T, N>::BitmapOverlappedAtlasStorage() { }
|
||||
|
||||
template <typename T, int N>
|
||||
BitmapOverlappedAtlasStorage<T, N>::BitmapOverlappedAtlasStorage(int width, int height) : bitmap(width, height), stencil(width, height) {
|
||||
for (T *cur = (T *) bitmap, *end = cur+N*width*height; cur < end; ++cur)
|
||||
*cur = minPxVal<T>();
|
||||
memset((byte *) stencil, 0, sizeof(byte)*width*height);
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
BitmapOverlappedAtlasStorage<T, N>::BitmapOverlappedAtlasStorage(const BitmapOverlappedAtlasStorage<T, N> &orig, int width, int height) : bitmap(width, height) {
|
||||
for (T *cur = (T *) bitmap, *end = cur+N*width*height; cur < end; ++cur)
|
||||
*cur = minPxVal<T>();
|
||||
memset((byte *) stencil, 0, sizeof(byte)*width*height);
|
||||
blit(bitmap, orig.bitmap, 0, 0, 0, 0, std::min(width, orig.bitmap.width()), std::min(height, orig.bitmap.height()));
|
||||
blit(stencil, orig.stencil, 0, 0, 0, 0, std::min(width, orig.bitmap.width()), std::min(height, orig.bitmap.height()));
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
BitmapOverlappedAtlasStorage<T, N>::operator msdfgen::BitmapConstRef<T, N>() const {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
BitmapOverlappedAtlasStorage<T, N>::operator msdfgen::BitmapRef<T, N>() {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
BitmapOverlappedAtlasStorage<T, N>::operator msdfgen::Bitmap<T, N>() && {
|
||||
return (msdfgen::Bitmap<T, N> &&) bitmap;
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
template <typename S>
|
||||
void BitmapOverlappedAtlasStorage<T, N>::put(int x, int y, const msdfgen::BitmapConstRef<S, N> &subBitmap) {
|
||||
blend((msdfgen::BitmapRef<T, N>) bitmap, subBitmap, x, y, 0, 0, subBitmap.width, subBitmap.height);
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
void BitmapOverlappedAtlasStorage<T, N>::get(int x, int y, const msdfgen::BitmapRef<T, N> &subBitmap) const {
|
||||
blit(subBitmap, bitmap, 0, 0, x, y, subBitmap.width, subBitmap.height);
|
||||
}
|
||||
|
||||
#define MSDF_ATLAS_BITMAP_OVERLAPPED_ATLAS_STORAGE_BOUND_AREA() { \
|
||||
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; \
|
||||
if (sy < 0) h += sy, dy -= sy, sy = 0; \
|
||||
w = std::max(0, std::min(w, std::min(dst.width-dx, src.width-sx))); \
|
||||
h = std::max(0, std::min(h, std::min(dst.height-dy, src.height-sy))); \
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
void BitmapOverlappedAtlasStorage<T, N>::blend(const msdfgen::BitmapRef<byte, N> &dst, const msdfgen::BitmapConstRef<byte, N> &src, int dx, int dy, int sx, int sy, int w, int h) {
|
||||
MSDF_ATLAS_BITMAP_OVERLAPPED_ATLAS_STORAGE_BOUND_AREA();
|
||||
for (int y = 0; y < h; ++y) {
|
||||
byte *dstPixel = dst(dx, dy+y);
|
||||
const byte *srcPixel = src(sx, sy+y);
|
||||
byte *stencilPixel = stencil(dx, dy+y);
|
||||
for (int x = 0; x < w; ++x) {
|
||||
for (int i = 0; i < N; ++i, ++dstPixel, ++srcPixel) {
|
||||
if (*dstPixel != *srcPixel) {
|
||||
if (*stencilPixel)
|
||||
*dstPixel = minPxVal<byte>();
|
||||
else
|
||||
*dstPixel = *srcPixel;
|
||||
}
|
||||
}
|
||||
*stencilPixel++ = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
void BitmapOverlappedAtlasStorage<T, N>::blend(const msdfgen::BitmapRef<byte, N> &dst, const msdfgen::BitmapConstRef<float, N> &src, int dx, int dy, int sx, int sy, int w, int h) {
|
||||
MSDF_ATLAS_BITMAP_OVERLAPPED_ATLAS_STORAGE_BOUND_AREA();
|
||||
for (int y = 0; y < h; ++y) {
|
||||
byte *dstPixel = dst(dx, dy+y);
|
||||
const float *srcPixel = src(sx, sy+y);
|
||||
byte *stencilPixel = stencil(dx, dy+y);
|
||||
for (int x = 0; x < w; ++x) {
|
||||
for (int i = 0; i < N; ++i, ++dstPixel, ++srcPixel) {
|
||||
byte srcByte = msdfgen::pixelFloatToByte(*srcPixel);
|
||||
if (*dstPixel != srcByte) {
|
||||
if (*stencilPixel)
|
||||
*dstPixel = minPxVal<byte>();
|
||||
else
|
||||
*dstPixel = srcByte;
|
||||
}
|
||||
}
|
||||
*stencilPixel++ = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
void BitmapOverlappedAtlasStorage<T, N>::blend(const msdfgen::BitmapRef<float, N> &dst, const msdfgen::BitmapConstRef<float, N> &src, int dx, int dy, int sx, int sy, int w, int h) {
|
||||
MSDF_ATLAS_BITMAP_OVERLAPPED_ATLAS_STORAGE_BOUND_AREA();
|
||||
for (int y = 0; y < h; ++y) {
|
||||
float *dstPixel = dst(dx, dy+y);
|
||||
const float *srcPixel = src(sx, sy+y);
|
||||
byte *stencilPixel = stencil(dx, dy+y);
|
||||
for (int x = 0; x < w; ++x) {
|
||||
for (int i = 0; i < N; ++i, ++dstPixel, ++srcPixel) {
|
||||
if (*dstPixel != *srcPixel) {
|
||||
if (*stencilPixel)
|
||||
*dstPixel = minPxVal<float>();
|
||||
else
|
||||
*dstPixel = *srcPixel;
|
||||
}
|
||||
}
|
||||
*stencilPixel++ = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef MSDF_ATLAS_BITMAP_OVERLAPPED_ATLAS_STORAGE_BOUND_AREA
|
||||
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@ public:
|
|||
void setThreadCount(int threadCount);
|
||||
/// Allows access to the underlying AtlasStorage
|
||||
const AtlasStorage &atlasStorage() const;
|
||||
AtlasStorage &atlasStorage();
|
||||
/// Returns the layout of the contained glyphs as a list of GlyphBoxes
|
||||
const std::vector<GlyphBox> &getLayout() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,11 @@ const AtlasStorage &ImmediateAtlasGenerator<T, N, GEN_FN, AtlasStorage>::atlasSt
|
|||
return storage;
|
||||
}
|
||||
|
||||
template <typename T, int N, GeneratorFunction<T, N> GEN_FN, class AtlasStorage>
|
||||
AtlasStorage &ImmediateAtlasGenerator<T, N, GEN_FN, AtlasStorage>::atlasStorage() {
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -329,12 +329,33 @@ struct Configuration {
|
|||
const char *shadronPreviewText;
|
||||
};
|
||||
|
||||
template <typename T, int N>
|
||||
struct CondEC {
|
||||
static void condEC(const msdfgen::BitmapRef<T, N> &sdf, msdfgen::Range pxRange, double minDeviationRatio) { }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct CondEC<float, 3> {
|
||||
static void condEC(const msdfgen::BitmapRef<float, 3> &sdf, msdfgen::Range pxRange, double minDeviationRatio) {
|
||||
puts("EC activated");
|
||||
msdfgen::msdfFastEdgeErrorCorrection(sdf, pxRange, minDeviationRatio);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct CondEC<float, 4> {
|
||||
static void condEC(const msdfgen::BitmapRef<float, 4> &sdf, msdfgen::Range pxRange, double minDeviationRatio) {
|
||||
puts("EC activated");
|
||||
msdfgen::msdfFastEdgeErrorCorrection(sdf, pxRange, minDeviationRatio);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename S, int N, GeneratorFunction<S, N> GEN_FN>
|
||||
static bool makeAtlas(const std::vector<GlyphGeometry> &glyphs, const std::vector<FontGeometry> &fonts, const Configuration &config) {
|
||||
ImmediateAtlasGenerator<S, N, GEN_FN, BitmapAtlasStorage<T, N> > generator(config.width, config.height);
|
||||
ImmediateAtlasGenerator<S, N, GEN_FN, BitmapOverlappedAtlasStorage<T, N> > generator(config.width, config.height);
|
||||
generator.setAttributes(config.generatorAttributes);
|
||||
generator.setThreadCount(config.threadCount);
|
||||
generator.generate(glyphs.data(), glyphs.size());
|
||||
CondEC<T, N>::condEC((msdfgen::BitmapRef<T, N>) generator.atlasStorage(), config.pxRange, config.generatorAttributes.config.errorCorrection.minDeviationRatio);
|
||||
msdfgen::BitmapConstRef<T, N> bitmap = (msdfgen::BitmapConstRef<T, N>) generator.atlasStorage();
|
||||
|
||||
bool success = true;
|
||||
|
|
@ -1064,7 +1085,7 @@ int main(int argc, const char *const *argv) {
|
|||
config.imageFormat == ImageFormat::BINARY_FLOAT_BE
|
||||
);
|
||||
// TODO: In this case (if spacing is -1), the border pixels of each glyph are black, but still computed. For floating-point output, this may play a role.
|
||||
int spacing = config.imageType == ImageType::MSDF || config.imageType == ImageType::MTSDF ? 0 : -1;
|
||||
int spacing = -1;
|
||||
double uniformOriginX, uniformOriginY;
|
||||
|
||||
// Load fonts
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "bitmap-blit.h"
|
||||
#include "AtlasStorage.h"
|
||||
#include "BitmapAtlasStorage.h"
|
||||
#include "BitmapOverlappedAtlasStorage.h"
|
||||
#include "TightAtlasPacker.h"
|
||||
#include "GridAtlasPacker.h"
|
||||
#include "AtlasGenerator.h"
|
||||
|
|
|
|||
2
msdfgen
2
msdfgen
|
|
@ -1 +1 @@
|
|||
Subproject commit 85e8b3d47b3d1a42e4a5ebda0a24fb1cc2e669e0
|
||||
Subproject commit 755c45b4445baa12bfead90fa7d4d2259f2a14c4
|
||||
Loading…
Reference in New Issue