2017-01-30 02:37:56 +00:00
|
|
|
#include "loaders/font.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include <ft2build.h>
|
|
|
|
#include FT_FREETYPE_H
|
|
|
|
#include FT_GLYPH_H
|
|
|
|
|
|
|
|
static FT_Library ft = NULL;
|
|
|
|
|
2017-02-06 04:30:17 +00:00
|
|
|
FontData* lovrFontDataCreate(void* data, int size, int height) {
|
2017-01-30 02:37:56 +00:00
|
|
|
if (!ft && FT_Init_FreeType(&ft)) {
|
|
|
|
error("Error initializing FreeType");
|
|
|
|
}
|
|
|
|
|
|
|
|
FontData* fontData = malloc(sizeof(FontData));
|
2017-02-06 04:30:17 +00:00
|
|
|
fontData->size = height;
|
|
|
|
|
|
|
|
FT_Error err = FT_Err_Ok;
|
|
|
|
err = err || FT_New_Memory_Face(ft, data, size, 0, (FT_Face*)&fontData->rasterizer);
|
|
|
|
err = err || FT_Set_Pixel_Sizes(fontData->rasterizer, 0, height);
|
2017-01-30 02:37:56 +00:00
|
|
|
|
2017-02-06 04:30:17 +00:00
|
|
|
if (err) {
|
|
|
|
error("Problem loading font\n");
|
2017-01-30 02:37:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return fontData;
|
|
|
|
}
|
|
|
|
|
2017-02-06 04:30:17 +00:00
|
|
|
void lovrFontDataDestroy(FontData* fontData) {
|
|
|
|
FT_Done_Face(fontData->rasterizer);
|
|
|
|
free(fontData);
|
|
|
|
}
|
|
|
|
|
2017-02-05 06:21:41 +00:00
|
|
|
void lovrFontDataLoadGlyph(FontData* fontData, uint32_t character, Glyph* glyph) {
|
2017-02-03 23:16:30 +00:00
|
|
|
FT_Face face = fontData->rasterizer;
|
|
|
|
FT_Error err = FT_Err_Ok;
|
2017-02-06 04:30:17 +00:00
|
|
|
FT_Glyph slot;
|
|
|
|
FT_Bitmap bitmap;
|
|
|
|
FT_BitmapGlyph bmglyph;
|
|
|
|
FT_Glyph_Metrics* metrics;
|
2017-01-30 02:37:56 +00:00
|
|
|
|
2017-02-06 04:30:17 +00:00
|
|
|
// FreeType stuff
|
|
|
|
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);
|
2017-02-03 23:16:30 +00:00
|
|
|
|
|
|
|
if (err) {
|
|
|
|
error("Error loading glyph\n");
|
|
|
|
}
|
|
|
|
|
2017-02-06 04:30:17 +00:00
|
|
|
bmglyph = (FT_BitmapGlyph) slot;
|
|
|
|
bitmap = bmglyph->bitmap;
|
|
|
|
metrics = &face->glyph->metrics;
|
2017-02-03 23:16:30 +00:00
|
|
|
|
2017-02-06 04:30:17 +00:00
|
|
|
// Initialize glyph
|
2017-02-05 06:21:41 +00:00
|
|
|
glyph->x = 0;
|
|
|
|
glyph->y = 0;
|
|
|
|
glyph->w = metrics->width >> 6;
|
|
|
|
glyph->h = metrics->height >> 6;
|
2017-02-06 04:30:17 +00:00
|
|
|
glyph->dx = metrics->horiBearingX >> 6;
|
|
|
|
glyph->dy = metrics->horiBearingY >> 6;
|
2017-02-05 06:21:41 +00:00
|
|
|
glyph->advance = metrics->horiAdvance >> 6;
|
2017-02-06 04:30:17 +00:00
|
|
|
glyph->data = malloc(glyph->w * glyph->h * 2 * sizeof(uint8_t));
|
2017-02-03 23:16:30 +00:00
|
|
|
|
2017-02-06 04:30:17 +00:00
|
|
|
// Transform data into an OpenGL-friendly format
|
2017-02-03 23:16:30 +00:00
|
|
|
int i = 0;
|
2017-02-06 04:30:17 +00:00
|
|
|
uint8_t* row = bitmap.buffer;
|
2017-02-05 06:21:41 +00:00
|
|
|
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];
|
2017-02-03 23:16:30 +00:00
|
|
|
}
|
2017-02-06 04:30:17 +00:00
|
|
|
row += bitmap.pitch;
|
2017-02-03 23:16:30 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 04:30:17 +00:00
|
|
|
FT_Done_Glyph(slot);
|
2017-01-30 02:37:56 +00:00
|
|
|
}
|