Some work on rendering glyphs.

This commit is contained in:
Josh Holtrop 2020-12-03 22:31:55 -05:00
parent 6ff4bdcc11
commit 2ab09b47bf
2 changed files with 98 additions and 6 deletions

View File

@ -11,10 +11,10 @@ static bool Initialized;
typedef struct typedef struct
{ {
FT_Face face;
int32_t advance; int32_t advance;
int32_t line_height; int32_t line_height;
int32_t baseline_offset; int32_t baseline_offset;
FT_Face face;
} Font; } Font;
typedef struct typedef struct

View File

@ -1,7 +1,15 @@
module jes.gui.font; module jes.gui.font;
import std.string; import std.string;
import derelict.opengl;
import gltk;
import core.stdc.string;
struct CFont; struct CFont
{
int advance;
int line_height;
int baseline_offset;
}
struct CGlyph struct CGlyph
{ {
@ -20,20 +28,72 @@ private extern(C) void Font_Free(CFont * font);
class Font class Font
{ {
private static __gshared Glyph[uint] glyphs;
class Glyph class Glyph
{ {
int advance; int advance;
gltk.Texture m_texture;
gltk.Buffer m_buffer;
gltk.Array m_array;
this(const(CGlyph) * cglyph)
{
advance = cglyph.advance;
m_texture = new gltk.Texture();
m_texture.bind(GL_TEXTURE_2D);
int rounded_width = gltk.Texture.next_power_of_2(cglyph.width);
int rounded_height = gltk.Texture.next_power_of_2(cglyph.height);
ubyte[] texture = new ubyte[rounded_width * rounded_height];
memset(texture.ptr, 0, rounded_width * rounded_height);
for (int i = 0; i < cglyph.height; i++)
{
memcpy(&texture[rounded_width * i],
&cglyph.bitmap[cglyph.width * (cglyph.height - i - 1)],
cglyph.width);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, rounded_width, rounded_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texture.ptr);
m_array = new gltk.Array();
m_array.bind();
int left = cglyph.left;
int top = cglyph.top;
float s_max = cglyph.width / cast(float)rounded_width;
float t_max = cglyph.height / cast(float)rounded_height;
m_buffer = new gltk.Buffer();
GLfloat[] data = [
cast(GLfloat)left, cast(GLfloat)(top - cglyph.height), 0.0, 0.0,
cast(GLfloat)(left + cglyph.width), cast(GLfloat)(top - cglyph.height), s_max, 0.0,
cast(GLfloat)left, cast(GLfloat)top, 0.0, t_max,
cast(GLfloat)(left + cglyph.width), cast(GLfloat)top, s_max, t_max,
];
m_buffer.set_buffer_data(GL_ARRAY_BUFFER, GL_STATIC_DRAW, data.ptr, data.length);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, null);
}
void render() void render()
{ {
m_array.bind();
m_texture.bind(GL_TEXTURE_2D);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
} }
} }
CFont * font; CFont * m_font;
this(const char * fname, int size) this(const char * fname, int size)
{ {
font = Font_Load(fname, size); m_font = Font_Load(fname, size);
if (font == null) if (m_font == null)
{ {
throw new Exception("Could not load font"); throw new Exception("Could not load font");
} }
@ -46,6 +106,38 @@ class Font
~this() ~this()
{ {
Font_Free(font); Font_Free(m_font);
}
@property int advance()
{
return m_font.advance;
}
@property int line_height()
{
return m_font.line_height;
}
@property int baseline_offset()
{
return m_font.baseline_offset;
}
Glyph get_glyph(uint char_code)
{
if (char_code in glyphs)
{
return glyphs[char_code];
}
Glyph glyph;
CGlyph * cglyph = Font_LoadGlyph(m_font, char_code);
if (cglyph != null)
{
glyph = new Glyph(cglyph);
Font_FreeGlyph(cglyph);
}
glyphs[char_code] = glyph;
return glyph;
} }
} }