Use msdfgen;

This commit is contained in:
bjorn 2017-07-15 00:18:25 +09:00
parent c518cadcf7
commit 800d07a0de
3 changed files with 74 additions and 27 deletions

View File

@ -48,7 +48,7 @@ Font* lovrFontCreate(FontData* fontData) {
}
// Texture
TextureData* textureData = lovrTextureDataGetBlank(font->atlas.width, font->atlas.height, 0x0, FORMAT_LUMINANCE_ALPHA);
TextureData* textureData = lovrTextureDataGetBlank(font->atlas.width, font->atlas.height, 0x0, FORMAT_RGB);
font->texture = lovrTextureCreate(textureData);
lovrTextureSetWrap(font->texture, WRAP_CLAMP, WRAP_CLAMP);
@ -120,9 +120,9 @@ void lovrFontPrint(Font* font, const char* str, mat4 transform, float wrap, Hori
float x2 = x1 + glyph->w;
float y2 = y1 - glyph->h;
float s1 = glyph->x / u;
float t1 = glyph->y / v;
float t1 = (glyph->y + glyph->h) / v;
float s2 = (glyph->x + glyph->w) / u;
float t2 = (glyph->y + glyph->h) / v;
float t2 = glyph->y / v;
float vertices[30] = {
x1, y1, 0, s1, t1,
@ -287,7 +287,7 @@ void lovrFontAddGlyph(Font* font, Glyph* glyph) {
// Paste glyph into texture
lovrGraphicsBindTexture(font->texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, atlas->x, atlas->y, glyph->w, glyph->h, lovrTextureFormats[FORMAT_LUMINANCE_ALPHA].format, GL_UNSIGNED_BYTE, glyph->data);
glTexSubImage2D(GL_TEXTURE_2D, 0, atlas->x, atlas->y, glyph->w, glyph->h, lovrTextureFormats[FORMAT_RGB].format, GL_UNSIGNED_BYTE, glyph->data);
// Advance atlas cursor
atlas->x += glyph->w + atlas->padding;

View File

@ -55,7 +55,7 @@ void lovrGraphicsInit() {
glfwSetTime(0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
#ifndef LOVR_WEB
glfwSwapInterval(0);
glEnable(GL_LINE_SMOOTH);

View File

@ -1,12 +1,65 @@
#include "loaders/font.h"
#include "data/Cabin.ttf.h"
#include "util.h"
#include "msdfgen-c.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_OUTLINE_H
static FT_Library ft = NULL;
typedef struct {
float x;
float y;
msShape* shape;
msContour* contour;
} ftContext;
static int ftMoveTo(const FT_Vector* to, void* userdata) {
ftContext* context = userdata;
context->contour = msShapeAddContour(context->shape);
context->x = to->x / 64.;
context->y = to->y / 64.;
return 0;
}
static int ftLineTo(const FT_Vector* to, void* userdata) {
ftContext* context = userdata;
float x = to->x / 64.;
float y = to->y / 64.;
msContourAddLinearEdge(context->contour, context->x, context->y, x, y);
context->x = x;
context->y = y;
return 0;
}
static int ftConicTo(const FT_Vector* control, const FT_Vector* to, void* userdata) {
ftContext* context = userdata;
float cx = control->x / 64.;
float cy = control->y / 64.;
float x = to->x / 64.;
float y = to->y / 64.;
msContourAddQuadraticEdge(context->contour, context->x, context->y, cx, cy, x, y);
context->x = x;
context->y = y;
return 0;
}
static int ftCubicTo(const FT_Vector* control1, const FT_Vector* control2, const FT_Vector* to, void* userdata) {
ftContext* context = userdata;
float c1x = control1->x / 64.;
float c1y = control1->y / 64.;
float c2x = control2->x / 64.;
float c2y = control2->y / 64.;
float x = to->x / 64.;
float y = to->y / 64.;
msContourAddCubicEdge(context->contour, context->x, context->y, c1x, c1y, c2x, c2y, x, y);
context->x = x;
context->y = y;
return 0;
}
FontData* lovrFontDataCreate(Blob* blob, int size) {
if (!ft && FT_Init_FreeType(&ft)) {
error("Error initializing FreeType");
@ -51,22 +104,23 @@ void lovrFontDataDestroy(FontData* fontData) {
void lovrFontDataLoadGlyph(FontData* fontData, uint32_t character, Glyph* glyph) {
FT_Face face = fontData->rasterizer;
FT_Error err = FT_Err_Ok;
FT_Glyph slot;
FT_Bitmap bitmap;
FT_BitmapGlyph bmglyph;
FT_Glyph_Metrics* metrics;
FT_Outline_Funcs callbacks = {
.move_to = ftMoveTo,
.line_to = ftLineTo,
.conic_to = ftConicTo,
.cubic_to = ftCubicTo
};
msShape* shape = msShapeCreate();
ftContext context = { .x = 0, .y = 0, .shape = shape, .contour = NULL };
// FreeType
err = err || FT_Load_Glyph(face, FT_Get_Char_Index(face, character), FT_LOAD_DEFAULT);
err = err || FT_Get_Glyph(face->glyph, &slot);
err = err || FT_Glyph_To_Bitmap(&slot, FT_RENDER_MODE_NORMAL, 0, 1);
err = err || FT_Outline_Decompose(&face->glyph->outline, &callbacks, &context);
if (err) {
error("Error loading glyph\n");
}
bmglyph = (FT_BitmapGlyph) slot;
bitmap = bmglyph->bitmap;
metrics = &face->glyph->metrics;
// Initialize glyph
@ -77,20 +131,13 @@ void lovrFontDataLoadGlyph(FontData* fontData, uint32_t character, Glyph* glyph)
glyph->dx = metrics->horiBearingX >> 6;
glyph->dy = metrics->horiBearingY >> 6;
glyph->advance = metrics->horiAdvance >> 6;
glyph->data = malloc(glyph->w * glyph->h * 2 * sizeof(uint8_t));
glyph->data = malloc(glyph->w * glyph->h * 3 * sizeof(uint8_t));
// Transform data into an OpenGL-friendly format
int i = 0;
uint8_t* row = bitmap.buffer;
for (int y = 0; y < glyph->h; y++) {
for (int x = 0; x < glyph->w; x++) {
glyph->data[i++] = 0xff;
glyph->data[i++] = row[x];
}
row += bitmap.pitch;
}
FT_Done_Glyph(slot);
// Render SDF
msShapeNormalize(shape);
msEdgeColoringSimple(shape, 3.0, 0);
msGenerateMSDF(glyph->data, glyph->w, glyph->h, shape, fontData->size / 8., 1, 1, -glyph->dx, glyph->h - glyph->dy);
msShapeDestroy(shape);
}
int lovrFontDataGetKerning(FontData* fontData, uint32_t left, uint32_t right) {