mirror of https://github.com/bjornbytes/lovr.git
Use msdfgen;
This commit is contained in:
parent
c518cadcf7
commit
800d07a0de
|
@ -48,7 +48,7 @@ Font* lovrFontCreate(FontData* fontData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Texture
|
// 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);
|
font->texture = lovrTextureCreate(textureData);
|
||||||
lovrTextureSetWrap(font->texture, WRAP_CLAMP, WRAP_CLAMP);
|
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 x2 = x1 + glyph->w;
|
||||||
float y2 = y1 - glyph->h;
|
float y2 = y1 - glyph->h;
|
||||||
float s1 = glyph->x / u;
|
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 s2 = (glyph->x + glyph->w) / u;
|
||||||
float t2 = (glyph->y + glyph->h) / v;
|
float t2 = glyph->y / v;
|
||||||
|
|
||||||
float vertices[30] = {
|
float vertices[30] = {
|
||||||
x1, y1, 0, s1, t1,
|
x1, y1, 0, s1, t1,
|
||||||
|
@ -287,7 +287,7 @@ void lovrFontAddGlyph(Font* font, Glyph* glyph) {
|
||||||
|
|
||||||
// Paste glyph into texture
|
// Paste glyph into texture
|
||||||
lovrGraphicsBindTexture(font->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
|
// Advance atlas cursor
|
||||||
atlas->x += glyph->w + atlas->padding;
|
atlas->x += glyph->w + atlas->padding;
|
||||||
|
|
|
@ -55,7 +55,7 @@ void lovrGraphicsInit() {
|
||||||
glfwSetTime(0);
|
glfwSetTime(0);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
#ifndef LOVR_WEB
|
#ifndef LOVR_WEB
|
||||||
glfwSwapInterval(0);
|
glfwSwapInterval(0);
|
||||||
glEnable(GL_LINE_SMOOTH);
|
glEnable(GL_LINE_SMOOTH);
|
||||||
|
|
|
@ -1,12 +1,65 @@
|
||||||
#include "loaders/font.h"
|
#include "loaders/font.h"
|
||||||
#include "data/Cabin.ttf.h"
|
#include "data/Cabin.ttf.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "msdfgen-c.h"
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
#include FT_GLYPH_H
|
#include FT_GLYPH_H
|
||||||
|
#include FT_OUTLINE_H
|
||||||
|
|
||||||
static FT_Library ft = NULL;
|
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) {
|
FontData* lovrFontDataCreate(Blob* blob, int size) {
|
||||||
if (!ft && FT_Init_FreeType(&ft)) {
|
if (!ft && FT_Init_FreeType(&ft)) {
|
||||||
error("Error initializing FreeType");
|
error("Error initializing FreeType");
|
||||||
|
@ -51,22 +104,23 @@ void lovrFontDataDestroy(FontData* fontData) {
|
||||||
void lovrFontDataLoadGlyph(FontData* fontData, uint32_t character, Glyph* glyph) {
|
void lovrFontDataLoadGlyph(FontData* fontData, uint32_t character, Glyph* glyph) {
|
||||||
FT_Face face = fontData->rasterizer;
|
FT_Face face = fontData->rasterizer;
|
||||||
FT_Error err = FT_Err_Ok;
|
FT_Error err = FT_Err_Ok;
|
||||||
FT_Glyph slot;
|
|
||||||
FT_Bitmap bitmap;
|
|
||||||
FT_BitmapGlyph bmglyph;
|
|
||||||
FT_Glyph_Metrics* metrics;
|
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_Load_Glyph(face, FT_Get_Char_Index(face, character), FT_LOAD_DEFAULT);
|
||||||
err = err || FT_Get_Glyph(face->glyph, &slot);
|
err = err || FT_Outline_Decompose(&face->glyph->outline, &callbacks, &context);
|
||||||
err = err || FT_Glyph_To_Bitmap(&slot, FT_RENDER_MODE_NORMAL, 0, 1);
|
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
error("Error loading glyph\n");
|
error("Error loading glyph\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bmglyph = (FT_BitmapGlyph) slot;
|
|
||||||
bitmap = bmglyph->bitmap;
|
|
||||||
metrics = &face->glyph->metrics;
|
metrics = &face->glyph->metrics;
|
||||||
|
|
||||||
// Initialize glyph
|
// Initialize glyph
|
||||||
|
@ -77,20 +131,13 @@ void lovrFontDataLoadGlyph(FontData* fontData, uint32_t character, Glyph* glyph)
|
||||||
glyph->dx = metrics->horiBearingX >> 6;
|
glyph->dx = metrics->horiBearingX >> 6;
|
||||||
glyph->dy = metrics->horiBearingY >> 6;
|
glyph->dy = metrics->horiBearingY >> 6;
|
||||||
glyph->advance = metrics->horiAdvance >> 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
|
// Render SDF
|
||||||
int i = 0;
|
msShapeNormalize(shape);
|
||||||
uint8_t* row = bitmap.buffer;
|
msEdgeColoringSimple(shape, 3.0, 0);
|
||||||
for (int y = 0; y < glyph->h; y++) {
|
msGenerateMSDF(glyph->data, glyph->w, glyph->h, shape, fontData->size / 8., 1, 1, -glyph->dx, glyph->h - glyph->dy);
|
||||||
for (int x = 0; x < glyph->w; x++) {
|
msShapeDestroy(shape);
|
||||||
glyph->data[i++] = 0xff;
|
|
||||||
glyph->data[i++] = row[x];
|
|
||||||
}
|
|
||||||
row += bitmap.pitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
FT_Done_Glyph(slot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int lovrFontDataGetKerning(FontData* fontData, uint32_t left, uint32_t right) {
|
int lovrFontDataGetKerning(FontData* fontData, uint32_t left, uint32_t right) {
|
||||||
|
|
Loading…
Reference in New Issue