diff --git a/src/graphics/font.c b/src/graphics/font.c new file mode 100644 index 00000000..43331253 --- /dev/null +++ b/src/graphics/font.c @@ -0,0 +1,121 @@ +#include "graphics/font.h" +#include "graphics/graphics.h" +#include "graphics/texture.h" +#include "math/math.h" +#include "loaders/font.h" +#include "loaders/texture.h" +#include "vendor/vec/vec.h" +#include + +static vec_float_t scratch; + +Font* lovrFontCreate(FontData* fontData) { + Font* font = lovrAlloc(sizeof(Font), lovrFontDestroy); + if (!font) return NULL; + + font->fontData = fontData; + font->padding = 1; + font->tx = font->padding; + font->ty = font->padding; + font->tw = 256; + font->th = 256; + TextureData* textureData = lovrTextureDataGetBlank(font->tw, font->th, 0x00, FORMAT_RG); + glPixelStorei(GL_UNPACK_ALIGNMENT, 2); + font->texture = lovrTextureCreate(textureData); + lovrTextureSetWrap(font->texture, WRAP_CLAMP, WRAP_CLAMP); + int swizzle[] = { GL_RED, GL_RED, GL_RED, GL_GREEN }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle); + map_init(&font->glyphs); + + return font; +} + +void lovrFontDestroy(const Ref* ref) { + Font* font = containerof(ref, Font); + lovrFontDataDestroy(font->fontData); + free(font); +} + +void lovrFontDataDestroy(FontData* fontData) { + // TODO + free(fontData); +} + +void lovrFontPrint(Font* font, const char* str) { + vec_reserve(&scratch, strlen(str) * 30); + vec_clear(&scratch); + + // Cursor + float x = 0; + float y = 0; + + for (unsigned int i = 0; i < strlen(str); i++) { + Glyph* glyph = lovrFontGetGlyph(font, str[i]); + float s = glyph->s; + float t = glyph->t; + float w = glyph->glyphData->w; + float h = glyph->glyphData->h; + + float xx = x + glyph->glyphData->x; + float yy = y - glyph->glyphData->y; + + float v[30] = { + xx, yy, -5, s, t + h / font->th, + xx, yy + h, -5, s, t, + xx + w, yy, -5, s + w / font->tw, t + h / font->th, + xx + w, yy, -5, s + w / font->tw, t + h / font->th, + xx, yy + h, -5, s, t, + xx + w, yy + h, -5, s + w / font->tw, t + }; + + x += glyph->glyphData->advance; + + vec_pusharr(&scratch, v, 30); + } + + lovrGraphicsSetShapeData(scratch.data, scratch.length); + lovrGraphicsDrawPrimitive(GL_TRIANGLES, font->texture, 0, 1, 0); +} + +Glyph* lovrFontGetGlyph(Font* font, char character) { + + // Return the glyph if it's already loaded + char key[2] = { character, '\0' }; + Glyph** g = (Glyph**) map_get(&font->glyphs, key); + if (g) return *g; + + // Otherwise, load it (3 mallocs isn't great FIXME) + Glyph* glyph = malloc(sizeof(Glyph)); + glyph->glyphData = lovrFontDataCreateGlyph(font->fontData, character); + + // Put the glyph somewhere, expanding texture as necessary + while (font->tx + glyph->glyphData->w > font->tw - 2 * font->padding) { + while (font->ty + glyph->glyphData->h > font->th - 2 * font->padding) { + // Expand texture + } + font->tx = font->padding; + font->ty += font->rowHeight; + font->rowHeight = 0; + } + + // Calculate texture coordinate + glyph->s = font->tx / (float) font->tw; + glyph->t = font->ty / (float) font->th; + + // Upload glyph to texture + lovrGraphicsBindTexture(font->texture); + glTexSubImage2D( + GL_TEXTURE_2D, 0, + font->tx, font->ty, glyph->glyphData->w, glyph->glyphData->h, + GL_RG, GL_UNSIGNED_BYTE, glyph->glyphData->data + ); + + // Advance the texture cursor + font->tx += glyph->glyphData->w; + font->rowHeight = MAX(font->rowHeight, glyph->glyphData->h); + + // Write glyph to cache + map_set(&font->glyphs, key, glyph); + + return glyph; +} diff --git a/src/graphics/font.h b/src/graphics/font.h index 1475b3bc..b0517830 100644 --- a/src/graphics/font.h +++ b/src/graphics/font.h @@ -1,14 +1,45 @@ +#include "util.h" +#include "graphics/texture.h" +#include "vendor/map/map.h" +#include + #pragma once typedef struct { - int width; - int height; + int x; + int y; + int w; + int h; + int advance; + uint8_t* data; +} GlyphData; + +typedef struct { + void* rasterizer; +} FontData; + +// GlyphData along with the glyph's position in the texture atlas +typedef struct { + GlyphData* glyphData; + float s; + float t; } Glyph; typedef struct { - void* face; -} FontData; - -typedef struct { - FontData fontData; + Ref ref; + FontData* fontData; + Texture* texture; + int tx; + int ty; + int tw; + int th; + int rowHeight; + int padding; + map_void_t glyphs; } Font; + +Font* lovrFontCreate(FontData* fontData); +void lovrFontDestroy(const Ref* ref); +void lovrFontDataDestroy(FontData* fontData); +void lovrFontPrint(Font* font, const char* str); +Glyph* lovrFontGetGlyph(Font* font, char character); diff --git a/src/graphics/graphics.c b/src/graphics/graphics.c index 939043c0..31adfe77 100644 --- a/src/graphics/graphics.c +++ b/src/graphics/graphics.c @@ -21,7 +21,7 @@ void lovrGraphicsInit() { state.fullscreenShader = lovrShaderCreate(lovrNoopVertexShader, lovrDefaultFragmentShader); int uniformId = lovrShaderGetUniformId(state.skyboxShader, "cube"); lovrShaderSendInt(state.skyboxShader, uniformId, 1); - state.defaultTexture = lovrTextureCreate(lovrTextureDataGetBlank(1, 1, 0xff)); + state.defaultTexture = lovrTextureCreate(lovrTextureDataGetBlank(1, 1, 0xff, FORMAT_RGBA)); glGenBuffers(1, &state.shapeBuffer); glGenBuffers(1, &state.shapeIndexBuffer); glGenVertexArrays(1, &state.shapeArray); @@ -182,6 +182,14 @@ void lovrGraphicsSetShader(Shader* shader) { } } +Font* lovrGraphicsGetFont() { + return state.activeFont; +} + +void lovrGraphicsSetFont(Font* font) { + state.activeFont = font; +} + void lovrGraphicsBindTexture(Texture* texture) { if (!texture) { texture = state.defaultTexture; @@ -348,6 +356,16 @@ void lovrGraphicsMatrixTransform(mat4 transform) { // Primitives +void lovrGraphicsSetShapeData(float* data, int length) { + vec_clear(&state.shapeData); + vec_pusharr(&state.shapeData, data, length); +} + +void lovrGraphicsSetIndexData(unsigned int* data, int length) { + vec_clear(&state.shapeIndices); + vec_pusharr(&state.shapeIndices, data, length); +} + void lovrGraphicsDrawPrimitive(GLenum mode, Texture* texture, int hasNormals, int hasTexCoords, int useIndices) { int stride = 3 + (hasNormals ? 3 : 0) + (hasTexCoords ? 2 : 0); int strideBytes = stride * sizeof(float); @@ -387,21 +405,18 @@ void lovrGraphicsDrawPrimitive(GLenum mode, Texture* texture, int hasNormals, in } void lovrGraphicsPoints(float* points, int count) { - vec_clear(&state.shapeData); - vec_pusharr(&state.shapeData, points, count); + lovrGraphicsSetShapeData(points, count); lovrGraphicsDrawPrimitive(GL_POINTS, NULL, 0, 0, 0); } void lovrGraphicsLine(float* points, int count) { - vec_clear(&state.shapeData); - vec_pusharr(&state.shapeData, points, count); + lovrGraphicsSetShapeData(points, count); lovrGraphicsDrawPrimitive(GL_LINE_STRIP, NULL, 0, 0, 0); } void lovrGraphicsTriangle(DrawMode mode, float* points) { if (mode == DRAW_MODE_LINE) { - vec_clear(&state.shapeData); - vec_pusharr(&state.shapeData, points, 9); + lovrGraphicsSetShapeData(points, 9); lovrGraphicsDrawPrimitive(GL_LINE_LOOP, NULL, 0, 0, 0); } else { float normal[3]; @@ -413,8 +428,7 @@ void lovrGraphicsTriangle(DrawMode mode, float* points) { points[6], points[7], points[8], normal[0], normal[1], normal[2] }; - vec_clear(&state.shapeData); - vec_pusharr(&state.shapeData, data, 18); + lovrGraphicsSetShapeData(data, 18); lovrGraphicsDrawPrimitive(GL_TRIANGLE_STRIP, NULL, 1, 0, 0); } } @@ -452,8 +466,7 @@ void lovrGraphicsPlane(DrawMode mode, Texture* texture, float x, float y, float -.5, -.5, 0 }; - vec_clear(&state.shapeData); - vec_pusharr(&state.shapeData, points, 12); + lovrGraphicsSetShapeData(points, 12); lovrGraphicsDrawPrimitive(GL_LINE_LOOP, NULL, 0, 0, 0); } else if (mode == DRAW_MODE_FILL) { float data[] = { @@ -463,8 +476,7 @@ void lovrGraphicsPlane(DrawMode mode, Texture* texture, float x, float y, float .5, -.5, 0, 0, 0, -1, 1, 1 }; - vec_clear(&state.shapeData); - vec_pusharr(&state.shapeData, data, 32); + lovrGraphicsSetShapeData(data, 32); lovrGraphicsDrawPrimitive(GL_TRIANGLE_STRIP, texture, 1, 1, 0); } @@ -483,8 +495,7 @@ void lovrGraphicsPlaneFullscreen(Texture* texture) { lovrRetain(&lastShader->ref); lovrGraphicsSetShader(state.fullscreenShader); - vec_clear(&state.shapeData); - vec_pusharr(&state.shapeData, data, 20); + lovrGraphicsSetShapeData(data, 20); lovrGraphicsDrawPrimitive(GL_TRIANGLE_STRIP, texture, 0, 1, 0); lovrGraphicsSetShader(lastShader); @@ -516,10 +527,8 @@ void lovrGraphicsCube(DrawMode mode, Texture* texture, mat4 transform) { 0, 4, 1, 5, 2, 6, 3, 7 // Connections }; - vec_clear(&state.shapeData); - vec_pusharr(&state.shapeData, points, 24); - vec_clear(&state.shapeIndices); - vec_pusharr(&state.shapeIndices, indices, 24); + lovrGraphicsSetShapeData(points, 24); + lovrGraphicsSetIndexData(indices, 24); lovrGraphicsDrawPrimitive(GL_LINES, NULL, 0, 0, 1); } else { float data[] = { @@ -564,8 +573,7 @@ void lovrGraphicsCube(DrawMode mode, Texture* texture, mat4 transform) { .5, .5, .5, 0, 1, 0, 1, 0 }; - vec_clear(&state.shapeData); - vec_pusharr(&state.shapeData, data, 208); + lovrGraphicsSetShapeData(data, 208); lovrGraphicsDrawPrimitive(GL_TRIANGLE_STRIP, texture, 1, 1, 0); } @@ -624,8 +632,7 @@ void lovrGraphicsSkybox(Skybox* skybox, float angle, float ax, float ay, float a 1.f, 1.f, 1.f }; - vec_clear(&state.shapeData); - vec_pusharr(&state.shapeData, cube, 156); + lovrGraphicsSetShapeData(cube, 156); glDepthMask(GL_FALSE); glActiveTexture(GL_TEXTURE1); @@ -644,3 +651,7 @@ void lovrGraphicsSkybox(Skybox* skybox, float angle, float ax, float ay, float a lovrRelease(&lastShader->ref); lovrGraphicsPop(); } + +void lovrGraphicsPrint(const char* str) { + lovrFontPrint(state.activeFont, str); +} diff --git a/src/graphics/graphics.h b/src/graphics/graphics.h index a269d340..a7a36fce 100644 --- a/src/graphics/graphics.h +++ b/src/graphics/graphics.h @@ -1,4 +1,5 @@ #include "graphics/buffer.h" +#include "graphics/font.h" #include "graphics/model.h" #include "graphics/shader.h" #include "graphics/skybox.h" @@ -48,6 +49,7 @@ typedef struct { Shader* defaultShader; Shader* skyboxShader; Shader* fullscreenShader; + Font* activeFont; Texture* defaultTexture; float transforms[MAX_TRANSFORMS][16]; CanvasState* canvases[MAX_CANVASES]; @@ -91,6 +93,8 @@ void lovrGraphicsGetScissor(int* x, int* y, int* width, int* height); void lovrGraphicsSetScissor(int x, int y, int width, int height); Shader* lovrGraphicsGetShader(); void lovrGraphicsSetShader(Shader* shader); +Font* lovrGraphicsGetFont(); +void lovrGraphicsSetFont(Font* font); void lovrGraphicsBindTexture(Texture* texture); mat4 lovrGraphicsGetProjection(); void lovrGraphicsSetProjection(float near, float far, float fov); @@ -124,6 +128,8 @@ void lovrGraphicsScale(float x, float y, float z); void lovrGraphicsMatrixTransform(mat4 transform); // Primitives +void lovrGraphicsSetShapeData(float* data, int length); +void lovrGraphicsSetIndexData(unsigned int* data, int length); void lovrGraphicsDrawPrimitive(GLenum mode, Texture* texture, int hasNormals, int hasTexCoords, int useIndices); void lovrGraphicsPoints(float* points, int count); void lovrGraphicsLine(float* points, int count); @@ -132,3 +138,4 @@ void lovrGraphicsPlane(DrawMode mode, Texture* texture, float x, float y, float void lovrGraphicsPlaneFullscreen(Texture* texture); void lovrGraphicsCube(DrawMode mode, Texture* texture, mat4 transform); void lovrGraphicsSkybox(Skybox* skybox, float angle, float ax, float ay, float az); +void lovrGraphicsPrint(const char* str); diff --git a/src/graphics/texture.c b/src/graphics/texture.c index 489a89ef..6e7b2b96 100644 --- a/src/graphics/texture.c +++ b/src/graphics/texture.c @@ -4,17 +4,29 @@ #include #include +static GLenum getGLFormat(TextureFormat format) { + switch (format) { + case FORMAT_RED: return GL_RED; + case FORMAT_RG: return GL_RG; + case FORMAT_RGB: return GL_RGB; + case FORMAT_RGBA: return GL_RGBA; + } + + return 0; +} + Texture* lovrTextureCreate(TextureData* textureData) { Texture* texture = lovrAlloc(sizeof(Texture), lovrTextureDestroy); if (!texture) return NULL; int w = textureData->width; int h = textureData->height; + GLenum format = getGLFormat(textureData->format); texture->textureData = textureData; glGenTextures(1, &texture->id); lovrTextureBind(texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData->data); + glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, textureData->data); lovrTextureSetFilter(texture, FILTER_LINEAR, FILTER_LINEAR); lovrTextureSetWrap(texture, WRAP_REPEAT, WRAP_REPEAT); diff --git a/src/graphics/texture.h b/src/graphics/texture.h index 963441e6..a6695cec 100644 --- a/src/graphics/texture.h +++ b/src/graphics/texture.h @@ -5,11 +5,19 @@ struct CanvasState; #pragma once +typedef enum { + FORMAT_RED, + FORMAT_RG, + FORMAT_RGB, + FORMAT_RGBA +} TextureFormat; + typedef struct { void* data; int width; int height; int channels; + TextureFormat format; } TextureData; typedef enum { diff --git a/src/loaders/font.c b/src/loaders/font.c index 27a24dce..c4b365b5 100644 --- a/src/loaders/font.c +++ b/src/loaders/font.c @@ -12,23 +12,55 @@ FontData* lovrFontDataCreate(void* data, int size) { } FontData* fontData = malloc(sizeof(FontData)); - FT_Face face = fontData->face; - if (FT_New_Memory_Face(ft, data, size, 0, &face)) { + if (FT_New_Memory_Face(ft, data, size, 0, (FT_Face*)&fontData->rasterizer)) { error("Error loading font"); } - if (FT_Set_Pixel_Sizes(face, 16, 16)) { + if (FT_Set_Pixel_Sizes(fontData->rasterizer, 0, 64)) { error("Problem setting font size"); } return fontData; } -void lovrFontDataGetGlyph(FontData* fontData, char c, Glyph* glyph) { - FT_Glyph ftglyph; - FT_Face face = fontData->face; - FT_Load_Glyph(face, c, FT_LOAD_DEFAULT); - FT_Get_Glyph(face->glyph, &ftglyph); +GlyphData* lovrFontDataCreateGlyph(FontData* fontData, uint32_t character) { + FT_Face face = fontData->rasterizer; + FT_Error err = FT_Err_Ok; + FT_Glyph ftGlyph; + FT_Bitmap ftBitmap; + FT_BitmapGlyph ftBitmapGlyph; - // + err |= FT_Load_Glyph(face, FT_Get_Char_Index(face, character), FT_LOAD_DEFAULT); + err |= FT_Get_Glyph(face->glyph, &ftGlyph); + err |= FT_Glyph_To_Bitmap(&ftGlyph, FT_RENDER_MODE_NORMAL, 0, 1); + + if (err) { + error("Error loading glyph\n"); + } + + ftBitmapGlyph = (FT_BitmapGlyph) ftGlyph; + ftBitmap = ftBitmapGlyph->bitmap; + + GlyphData* glyphData = malloc(sizeof(GlyphData)); + FT_Glyph_Metrics* metrics = &face->glyph->metrics; + glyphData->x = metrics->horiBearingX >> 6; + glyphData->y = metrics->horiBearingY >> 6; + glyphData->w = metrics->width >> 6; + glyphData->h = metrics->height >> 6; + glyphData->advance = metrics->horiAdvance >> 6; + glyphData->data = malloc(2 * glyphData->w * glyphData->h); + + int i = 0; + uint8_t* row = ftBitmap.buffer; + for (int y = 0; y < glyphData->h; y++) { + for (int x = 0; x < glyphData->w; x++) { + glyphData->data[i++] = 0xff; + glyphData->data[i++] = row[x]; + } + + row += ftBitmap.pitch; + } + + FT_Done_Glyph(ftGlyph); + return glyphData; } diff --git a/src/loaders/font.h b/src/loaders/font.h index cdee5995..618cd733 100644 --- a/src/loaders/font.h +++ b/src/loaders/font.h @@ -1,4 +1,5 @@ #include "graphics/font.h" +#include FontData* lovrFontDataCreate(void* data, int size); -void lovrFontDataGetGlyph(FontData* fontData, char c, Glyph* glyph); +GlyphData* lovrFontDataCreateGlyph(FontData* fontData, uint32_t characer); diff --git a/src/loaders/texture.c b/src/loaders/texture.c index b51dc335..123598d1 100644 --- a/src/loaders/texture.c +++ b/src/loaders/texture.c @@ -3,11 +3,18 @@ #include #include -TextureData* lovrTextureDataGetBlank(int width, int height, uint8_t value) { +TextureData* lovrTextureDataGetBlank(int width, int height, uint8_t value, TextureFormat format) { TextureData* textureData = malloc(sizeof(TextureData)); if (!textureData) return NULL; - int channels = 4; + int channels = 0; + switch (format) { + case FORMAT_RED: channels = 1; break; + case FORMAT_RG: channels = 2; break; + case FORMAT_RGB: channels = 3; break; + case FORMAT_RGBA: channels = 4; break; + } + int size = sizeof(uint8_t) * width * height * channels; uint8_t* data = malloc(size); memset(data, value, size); @@ -16,6 +23,7 @@ TextureData* lovrTextureDataGetBlank(int width, int height, uint8_t value) { textureData->width = width; textureData->height = height; textureData->channels = channels; + textureData->format = format; return textureData; } @@ -28,6 +36,7 @@ TextureData* lovrTextureDataGetEmpty(int width, int height) { textureData->width = width; textureData->height = height; textureData->channels = 4; + textureData->format = FORMAT_RGBA; return textureData; } @@ -44,6 +53,7 @@ TextureData* lovrTextureDataFromFile(void* data, int size) { if (image) { textureData->data = image; + textureData->format = FORMAT_RGBA; return textureData; } @@ -59,5 +69,6 @@ TextureData* lovrTextureDataFromOpenVRModel(OpenVRModel* vrModel) { textureData->width = texture->unWidth; textureData->height = texture->unHeight; textureData->data = texture->rubTextureMapData; + textureData->format = FORMAT_RGBA; return textureData; } diff --git a/src/loaders/texture.h b/src/loaders/texture.h index 86f55300..2eabb6e1 100644 --- a/src/loaders/texture.h +++ b/src/loaders/texture.h @@ -2,7 +2,7 @@ #include "openvr.h" #include -TextureData* lovrTextureDataGetBlank(int width, int height, uint8_t value); +TextureData* lovrTextureDataGetBlank(int width, int height, uint8_t value, TextureFormat format); TextureData* lovrTextureDataGetEmpty(int width, int height); TextureData* lovrTextureDataFromFile(void* data, int size); TextureData* lovrTextureDataFromOpenVRModel(OpenVRModel* vrModel); diff --git a/src/lovr/graphics.c b/src/lovr/graphics.c index 44c37ac1..5a4440a4 100644 --- a/src/lovr/graphics.c +++ b/src/lovr/graphics.c @@ -6,6 +6,7 @@ #include "lovr/types/texture.h" #include "lovr/types/transform.h" #include "graphics/graphics.h" +#include "loaders/font.h" #include "loaders/model.h" #include "loaders/texture.h" #include "filesystem/filesystem.h" @@ -68,6 +69,8 @@ const luaL_Reg lovrGraphics[] = { { "setScissor", l_lovrGraphicsSetScissor }, { "getShader", l_lovrGraphicsGetShader }, { "setShader", l_lovrGraphicsSetShader }, + { "getFont", l_lovrGraphicsGetFont }, + { "setFont", l_lovrGraphicsSetFont }, { "setProjection", l_lovrGraphicsSetProjection }, { "getLineWidth", l_lovrGraphicsGetLineWidth }, { "setLineWidth", l_lovrGraphicsSetLineWidth }, @@ -93,11 +96,13 @@ const luaL_Reg lovrGraphics[] = { { "triangle", l_lovrGraphicsTriangle }, { "plane", l_lovrGraphicsPlane }, { "cube", l_lovrGraphicsCube }, + { "print", l_lovrGraphicsPrint }, { "getWidth", l_lovrGraphicsGetWidth }, { "getHeight", l_lovrGraphicsGetHeight }, { "getDimensions", l_lovrGraphicsGetDimensions }, - { "newModel", l_lovrGraphicsNewModel }, { "newBuffer", l_lovrGraphicsNewBuffer }, + { "newFont", l_lovrGraphicsNewFont }, + { "newModel", l_lovrGraphicsNewModel }, { "newShader", l_lovrGraphicsNewShader }, { "newSkybox", l_lovrGraphicsNewSkybox }, { "newTexture", l_lovrGraphicsNewTexture }, @@ -110,6 +115,7 @@ int l_lovrGraphicsInit(lua_State* L) { lua_newtable(L); luaL_register(L, NULL, lovrGraphics); luax_registertype(L, "Buffer", lovrBuffer); + luax_registertype(L, "Font", NULL); luax_registertype(L, "Model", lovrModel); luax_registertype(L, "Shader", lovrShader); luax_registertype(L, "Skybox", lovrSkybox); @@ -311,6 +317,17 @@ int l_lovrGraphicsSetShader(lua_State* L) { return 0; } +int l_lovrGraphicsGetFont(lua_State* L) { + luax_pushtype(L, Font, lovrGraphicsGetFont()); + return 1; +} + +int l_lovrGraphicsSetFont(lua_State* L) { + Font* font = luax_checktype(L, 1, Font); + lovrGraphicsSetFont(font); + return 0; +} + int l_lovrGraphicsSetProjection(lua_State* L) { float near = luaL_checknumber(L, 1); float far = luaL_checknumber(L, 2); @@ -531,6 +548,12 @@ int l_lovrGraphicsCube(lua_State* L) { return 0; } +int l_lovrGraphicsPrint(lua_State* L) { + const char* str = luaL_checkstring(L, 1); + lovrGraphicsPrint(str); + return 0; +} + // Types int l_lovrGraphicsNewBuffer(lua_State* L) { @@ -600,6 +623,20 @@ int l_lovrGraphicsNewBuffer(lua_State* L) { return 1; } +int l_lovrGraphicsNewFont(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + //float size = luaL_optnumber(L, 2, 16); + int fileSize; + void* data = lovrFilesystemRead(path, &fileSize); + if (!data) { + luaL_error(L, "Could not load font '%s'", path); + } + FontData* fontData = lovrFontDataCreate(data, fileSize); + Font* font = lovrFontCreate(fontData); + luax_pushtype(L, Font, font); + return 1; +} + int l_lovrGraphicsNewModel(lua_State* L) { const char* path = lua_tostring(L, 1); int size; @@ -695,4 +732,3 @@ int l_lovrGraphicsNewTexture(lua_State* L) { luax_pushtype(L, Texture, texture); return 1; } - diff --git a/src/lovr/graphics.h b/src/lovr/graphics.h index 8bdc2036..149312e7 100644 --- a/src/lovr/graphics.h +++ b/src/lovr/graphics.h @@ -30,6 +30,8 @@ int l_lovrGraphicsGetScissor(lua_State* L); int l_lovrGraphicsSetScissor(lua_State* L); int l_lovrGraphicsGetShader(lua_State* L); int l_lovrGraphicsSetShader(lua_State* L); +int l_lovrGraphicsGetFont(lua_State* L); +int l_lovrGraphicsSetFont(lua_State* L); int l_lovrGraphicsSetProjection(lua_State* L); int l_lovrGraphicsGetLineWidth(lua_State* L); int l_lovrGraphicsSetLineWidth(lua_State* L); @@ -62,9 +64,11 @@ int l_lovrGraphicsLine(lua_State* L); int l_lovrGraphicsTriangle(lua_State* L); int l_lovrGraphicsPlane(lua_State* L); int l_lovrGraphicsCube(lua_State* L); +int l_lovrGraphicsPrint(lua_State* L); // Types int l_lovrGraphicsNewBuffer(lua_State* L); +int l_lovrGraphicsNewFont(lua_State* L); int l_lovrGraphicsNewModel(lua_State* L); int l_lovrGraphicsNewShader(lua_State* L); int l_lovrGraphicsNewSkybox(lua_State* L);