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
{
FT_Face face;
int32_t advance;
int32_t line_height;
int32_t baseline_offset;
FT_Face face;
} Font;
typedef struct

View File

@ -1,7 +1,15 @@
module jes.gui.font;
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
{
@ -20,20 +28,72 @@ private extern(C) void Font_Free(CFont * font);
class Font
{
private static __gshared Glyph[uint] glyphs;
class Glyph
{
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()
{
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)
{
font = Font_Load(fname, size);
if (font == null)
m_font = Font_Load(fname, size);
if (m_font == null)
{
throw new Exception("Could not load font");
}
@ -46,6 +106,38 @@ class Font
~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;
}
}