Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2025-10-05 08:22:47 +03:00
parent 4d8940812a
commit 9268380fd9
3 changed files with 88 additions and 1 deletions

View File

@@ -164,8 +164,10 @@ auto TextRenderer::generate_glyph(FontRuntime &rt, FontData &fd,
msdfgen::Bitmap<float, 3> msdf_bitmap(bmp_w, bmp_h);
msdfgen::Vector2 scale_vec(scale, scale);
double const inv_scale = 1.0 / scale;
msdfgen::Vector2 translate(
-bounds.l * scale + rt.px_range, -bounds.b * scale + rt.px_range);
-bounds.l + rt.px_range * inv_scale,
-bounds.b + rt.px_range * inv_scale);
msdfgen::generateMSDF(msdf_bitmap, shape, rt.px_range, scale_vec, translate);
std::vector<Color> buffer(static_cast<size_t>(bmp_w) * bmp_h);

BIN
tools/dump_msdf Executable file

Binary file not shown.

85
tools/dump_msdf.cpp Normal file
View File

@@ -0,0 +1,85 @@
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <string>
#include <msdfgen.h>
#include <ext/import-font.h>
static unsigned char clamp_channel(float v) {
if (v <= 0.0f) return 0;
if (v >= 1.0f) return 255;
return static_cast<unsigned char>(std::lround(v * 255.0f));
}
int main(int argc, char **argv) {
if (argc < 3) {
std::fprintf(stderr, "Usage: %s <font-file> <codepoint>\n", argv[0]);
return 1;
}
const char *fontPath = argv[1];
unsigned codepoint = std::strtoul(argv[2], nullptr, 0);
auto *ft = msdfgen::initializeFreetype();
if (!ft) return 1;
auto *font = msdfgen::loadFont(ft, fontPath);
if (!font) return 1;
msdfgen::Shape shape;
double advance = 0.0;
if (!msdfgen::loadGlyph(shape, font, msdfgen::GlyphIndex(codepoint), msdfgen::FONT_SCALING_EM_NORMALIZED, &advance)) {
std::fprintf(stderr, "Failed to load glyph %u\n", codepoint);
return 1;
}
shape.normalize();
msdfgen::edgeColoringSimple(shape, 3.0);
auto bounds = shape.getBounds();
double emScale = 48.0;
double pxRange = 4.0;
int bmp_w = std::max(1, (int)std::ceil((bounds.r - bounds.l) * emScale + 2.0 * pxRange));
int bmp_h = std::max(1, (int)std::ceil((bounds.t - bounds.b) * emScale + 2.0 * pxRange));
msdfgen::Bitmap<float, 3> bitmap(bmp_w, bmp_h);
msdfgen::Vector2 scale(emScale, emScale);
msdfgen::Vector2 translate(-bounds.l * emScale + pxRange, -bounds.b * emScale + pxRange);
msdfgen::generateMSDF(bitmap, shape, pxRange, scale, translate);
std::vector<unsigned char> buffer(static_cast<size_t>(bmp_w) * bmp_h * 4);
for (int y = 0; y < bmp_h; ++y) {
int dst_y = bmp_h - 1 - y;
for (int x = 0; x < bmp_w; ++x) {
const float *px = bitmap(x, y);
size_t idx = (static_cast<size_t>(dst_y) * bmp_w + x) * 4;
buffer[idx + 0] = clamp_channel(px[0]);
buffer[idx + 1] = clamp_channel(px[1]);
buffer[idx + 2] = clamp_channel(px[2]);
buffer[idx + 3] = 255;
}
}
int minX = bmp_w, minY = bmp_h, maxX = -1, maxY = -1;
for (int y = 0; y < bmp_h; ++y) {
for (int x = 0; x < bmp_w; ++x) {
size_t idx = (static_cast<size_t>(y) * bmp_w + x) * 4;
unsigned char r = buffer[idx];
unsigned char g = buffer[idx + 1];
unsigned char b = buffer[idx + 2];
bool interesting = !(r == 0 && g == 0 && b == 0) && !(r == 255 && g == 255 && b == 255);
if (interesting) {
if (x < minX) minX = x;
if (x > maxX) maxX = x;
if (y < minY) minY = y;
if (y > maxY) maxY = y;
}
}
}
std::printf("bmp %dx%d\n", bmp_w, bmp_h);
if (maxX >= minX && maxY >= minY) {
std::printf("interesting bbox: x=[%d,%d] y=[%d,%d]\n", minX, maxX, minY, maxY);
}
msdfgen::destroyFont(font);
msdfgen::deinitializeFreetype(ft);
return 0;
}